================ @@ -0,0 +1,585 @@ +//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the NestedNameSpecifier class, which represents +// a C++ nested-name-specifier. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H +#define LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H + +#include "clang/AST/DependenceFlags.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cstdint> +#include <cstdlib> +#include <utility> + +namespace clang { + +class ASTContext; +class CXXRecordDecl; +class NamedDecl; +class IdentifierInfo; +class LangOptions; +class NamespaceBaseDecl; +struct PrintingPolicy; +class Type; +class TypeLoc; + +struct NamespaceAndPrefix; +struct alignas(16) NamespaceAndPrefixStorage; + +/// Represents a C++ nested name specifier, such as +/// "\::std::vector<int>::". +/// +/// C++ nested name specifiers are the prefixes to qualified +/// names. For example, "foo::" in "foo::x" is a nested name +/// specifier. Nested name specifiers are made up of a sequence of +/// specifiers, each of which can be a namespace, type, decltype specifier, or +/// the global specifier ('::'). The last two specifiers can only appear at the +/// start of a nested-namespace-specifier. +class NestedNameSpecifier { + enum class FlagKind { Null, Global, Invalid }; + enum class StoredKind { + Type, + NamespaceOrSuper, + NamespaceWithGlobal, + NamespaceWithNamespace + }; + static constexpr uintptr_t FlagBits = 2, FlagMask = (1u << FlagBits) - 1u, + FlagOffset = 1, PtrOffset = FlagBits + FlagOffset, + PtrMask = (1u << PtrOffset) - 1u; + + uintptr_t StoredOrFlag; + + explicit NestedNameSpecifier(uintptr_t StoredOrFlag) + : StoredOrFlag(StoredOrFlag) {} + struct PtrKind { + StoredKind SK; + const void *Ptr; + }; + explicit NestedNameSpecifier(PtrKind PK) + : StoredOrFlag(uintptr_t(PK.Ptr) | (uintptr_t(PK.SK) << FlagOffset)) { + assert(PK.Ptr != nullptr); + assert((uintptr_t(PK.Ptr) & ((1u << PtrOffset) - 1u)) == 0); + assert((uintptr_t(PK.Ptr) >> PtrOffset) != 0); + } + + explicit constexpr NestedNameSpecifier(FlagKind K) + : StoredOrFlag(uintptr_t(K) << FlagOffset) {} + + bool isStoredKind() const { return (StoredOrFlag >> PtrOffset) != 0; } + + std::pair<StoredKind, const void *> getStored() const { + assert(isStoredKind()); + return {StoredKind(StoredOrFlag >> FlagOffset & FlagMask), + reinterpret_cast<const void *>(StoredOrFlag & ~PtrMask)}; + } + + FlagKind getFlagKind() const { + assert(!isStoredKind()); + return FlagKind(StoredOrFlag >> FlagOffset); + } + + static const NamespaceAndPrefixStorage * + MakeNamespaceAndPrefixStorage(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix); + static inline PtrKind MakeNamespacePtrKind(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix); + +public: + static constexpr NestedNameSpecifier getInvalid() { + return NestedNameSpecifier(FlagKind::Invalid); + } + + static constexpr NestedNameSpecifier getGlobal() { + return NestedNameSpecifier(FlagKind::Global); + } + + NestedNameSpecifier() : NestedNameSpecifier(FlagKind::Invalid) {} + + /// The kind of specifier that completes this nested name + /// specifier. + enum class Kind { + /// Empty. + Null, + + /// The global specifier '::'. There is no stored value. + Global, + + /// A type, stored as a Type*. + Type, + + /// A namespace-like entity, stored as a NamespaceBaseDecl*. + Namespace, + + /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of + /// the class it appeared in. + Super, + }; + + inline Kind getKind() const; ---------------- mizvekov wrote:
It does, an inline definition can't be provided here due to circular dependencies, but it is provided in `NestedNameSpecifier.h`. This is a way to get around the interdependence between `Decl.h` and `Type.h`. https://github.com/llvm/llvm-project/pull/147835 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits