Index: include/clang/AST/DeclarationName.h =================================================================== --- include/clang/AST/DeclarationName.h +++ include/clang/AST/DeclarationName.h @@ -17,6 +17,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMapInfo.h" @@ -32,14 +33,9 @@ class ASTContext; template class CanQual; -class CXXDeductionGuideNameExtra; -class CXXLiteralOperatorIdName; -class CXXOperatorIdName; -class CXXSpecialName; -class DeclarationNameExtra; -class IdentifierInfo; +class DeclarationName; +class DeclarationNameTable; class MultiKeywordSelector; -enum OverloadedOperatorKind : int; struct PrintingPolicy; class TemplateDecl; class TypeSourceInfo; @@ -47,50 +43,185 @@ using CanQualType = CanQual; -/// DeclarationName - The name of a declaration. In the common case, -/// this just stores an IdentifierInfo pointer to a normal -/// name. However, it also provides encodings for Objective-C -/// selectors (optimizing zero- and one-argument selectors, which make -/// up 78% percent of all selectors in Cocoa.h) and special C++ names -/// for constructors, destructors, and conversion functions. -class DeclarationName { +namespace detail { + +/// CXXSpecialNameExtra records the type associated with one of the "special" +/// kinds of declaration names in C++, e.g., constructors, destructors, and +/// conversion functions. Note that CXXSpecialName is used for C++ constructor, +/// destructor and conversion functions, but the actual kind is not stored in +/// CXXSpecialName. Instead we use three different FoldingSet +/// in DeclarationNameTable. +class alignas(IdentifierInfoAlignment) CXXSpecialNameExtra + : public llvm::FoldingSetNode { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; + + /// The type associated with this declaration name. + QualType Type; + + /// Extra information associated with this declaration name that + /// can be used by the front end. All bits are really needed + /// so it is not possible to stash something in the low order bits. + void *FETokenInfo; + + CXXSpecialNameExtra(QualType QT) : Type(QT), FETokenInfo(nullptr) {} + public: - /// NameKind - The kind of name this object contains. - enum NameKind { - Identifier, - ObjCZeroArgSelector, - ObjCOneArgSelector, - ObjCMultiArgSelector, - CXXConstructorName, - CXXDestructorName, - CXXConversionFunctionName, - CXXDeductionGuideName, - CXXOperatorName, - CXXLiteralOperatorName, - CXXUsingDirective - }; + void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddPointer(Type.getAsOpaquePtr()); + } +}; - static const unsigned NumNameKinds = CXXUsingDirective + 1; +/// Contains extra information for the name of a C++ deduction guide. +class alignas(IdentifierInfoAlignment) CXXDeductionGuideNameExtra + : public detail::DeclarationNameExtra, + public llvm::FoldingSetNode { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; -private: + /// The template named by the deduction guide. + TemplateDecl *Template; + + /// Extra information associated with this operator name that + /// can be used by the front end. All bits are really needed + /// so it is not possible to stash something in the low order bits. + void *FETokenInfo; + + CXXDeductionGuideNameExtra(TemplateDecl *TD) + : DeclarationNameExtra(CXXDeductionGuideName), Template(TD), + FETokenInfo(nullptr) {} + +public: + void Profile(llvm::FoldingSetNodeID &ID) { ID.AddPointer(Template); } +}; + +/// Contains extra information for the name of an overloaded operator +/// in C++, such as "operator+. This do not includes literal or conversion +/// operators. For literal operators see CXXLiteralOperatorIdName and for +/// conversion operators see CXXSpecialNameExtra. +class alignas(IdentifierInfoAlignment) CXXOperatorIdName { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; + + /// The kind of this operator. + OverloadedOperatorKind Kind = OO_None; + + /// Extra information associated with this operator name that + /// can be used by the front end. All bits are really needed + /// so it is not possible to stash something in the low order bits. + void *FETokenInfo = nullptr; +}; + +/// Contains the actual identifier that makes up the +/// name of a C++ literal operator. +class alignas(IdentifierInfoAlignment) CXXLiteralOperatorIdName + : public detail::DeclarationNameExtra, + public llvm::FoldingSetNode { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; + + IdentifierInfo *ID; + + /// Extra information associated with this operator name that + /// can be used by the front end. All bits are really needed + /// so it is not possible to stash something in the low order bits. + void *FETokenInfo; + + CXXLiteralOperatorIdName(IdentifierInfo *II) + : DeclarationNameExtra(CXXLiteralOperatorName), ID(II), + FETokenInfo(nullptr) {} + +public: + void Profile(llvm::FoldingSetNodeID &FSID) { FSID.AddPointer(ID); } +}; + +} // namespace detail + +/// The name of a declaration. In the common case, this just stores +/// an IdentifierInfo pointer to a normal name. However, it also provides +/// encodings for Objective-C selectors (optimizing zero- and one-argument +/// selectors, which make up 78% percent of all selectors in Cocoa.h), +/// special C++ names for constructors, destructors, and conversion functions, +/// and C++ overloaded operators. +class DeclarationName { friend class DeclarationNameTable; friend class NamedDecl; - /// StoredNameKind - The kind of name that is actually stored in the + /// StoredNameKind represent the kind of name that is actually stored in the /// upper bits of the Ptr field. This is only used internally. /// - /// Note: The entries here are synchronized with the entries in Selector, - /// for efficient translation between the two. + /// NameKind, StoredNameKind, and DeclarationNameExtra::ExtraKind + /// must satisfy the following properties. These properties enable + /// efficient conversion between the various kinds. + /// + /// * The first seven enumerators of StoredNameKind must have the same + /// numerical value as the first seven enumerators of NameKind. + /// This enable efficient conversion between the two enumerations + /// in the usual case. + /// + /// * The enumerations values of DeclarationNameExtra::ExtraKind must start + /// at zero, and correspond to the numerical value of the first non-inline + /// enumeration values of NameKind minus an offset. This makes conversion + /// between DeclarationNameExtra::ExtraKind and NameKind possible with + /// a single addition/substraction. + /// + /// * The enumeration values of Selector::IdentifierInfoFlag must correspond + /// to the relevant enumeration values of StoredNameKind. + /// More specifically: + /// * ZeroArg == StoredObjCZeroArgSelector, + /// * OneArg == StoredObjCOneArgSelector, + /// * MultiArg == StoredDeclarationNameExtra + /// + /// * PtrMask must mask the low 3 bits of Ptr. enum StoredNameKind { StoredIdentifier = 0, - StoredObjCZeroArgSelector = 0x01, - StoredObjCOneArgSelector = 0x02, - StoredDeclarationNameExtra = 0x03, - PtrMask = 0x03 + StoredObjCZeroArgSelector = Selector::ZeroArg, + StoredObjCOneArgSelector = Selector::OneArg, + StoredCXXConstructorName = 3, + StoredCXXDestructorName = 4, + StoredCXXConversionFunctionName = 5, + StoredCXXOperatorName = 6, + StoredDeclarationNameExtra = Selector::MultiArg, + PtrMask = 7, + UncommonNameKindOffset = 8 }; - /// Ptr - The lowest two bits are used to express what kind of name - /// we're actually storing, using the values of NameKind. Depending + static_assert(alignof(IdentifierInfo) >= 8 && + alignof(detail::DeclarationNameExtra) >= 8 && + alignof(detail::CXXSpecialNameExtra) >= 8 && + alignof(detail::CXXOperatorIdName) >= 8 && + alignof(detail::CXXDeductionGuideNameExtra) >= 8 && + alignof(detail::CXXLiteralOperatorIdName) >= 8, + "The various classes that DeclarationName::Ptr can point to" + " must be at least aligned to 8 bytes!"); + +public: + /// The kind of the name stored in this DeclarationName. + /// The first 7 enumeration values are stored inline and correspond + /// to frequently used kinds. The rest is stored in DeclarationNameExtra + /// and correspond to infrequently used kinds. + enum NameKind { + Identifier = StoredIdentifier, + ObjCZeroArgSelector = StoredObjCZeroArgSelector, + ObjCOneArgSelector = StoredObjCOneArgSelector, + CXXConstructorName = StoredCXXConstructorName, + CXXDestructorName = StoredCXXDestructorName, + CXXConversionFunctionName = StoredCXXConversionFunctionName, + CXXOperatorName = StoredCXXOperatorName, + CXXDeductionGuideName = UncommonNameKindOffset + + detail::DeclarationNameExtra::CXXDeductionGuideName, + CXXLiteralOperatorName = + UncommonNameKindOffset + + detail::DeclarationNameExtra::CXXLiteralOperatorName, + CXXUsingDirective = UncommonNameKindOffset + + detail::DeclarationNameExtra::CXXUsingDirective, + ObjCMultiArgSelector = UncommonNameKindOffset + + detail::DeclarationNameExtra::ObjCMultiArgSelector + }; + +private: + /// The lowest three bits of Ptr are used to express what kind of name + /// we're actually storing, using the values of StoredNameKind. Depending /// on the kind of name this is, the upper bits of Ptr may have one /// of several different meanings: /// @@ -105,99 +236,141 @@ /// with one argument, and Ptr is an IdentifierInfo pointer /// pointing to the selector name. /// + /// StoredCXXConstructorName - The name of a C++ constructor, + /// Ptr points to a CXXSpecialNameExtra. + /// + /// StoredCXXDestructorName - The name of a C++ destructor, + /// Ptr points to a CXXSpecialNameExtra. + /// + /// StoredCXXConversionFunctionName - The name of a C++ conversion function, + /// Ptr points to a CXXSpecialNameExtra. + /// + /// StoredCXXOperatorName - The name of an overloaded C++ operator, + /// Ptr points to a CXXOperatorIdName. + /// /// StoredDeclarationNameExtra - Ptr is actually a pointer to a /// DeclarationNameExtra structure, whose first value will tell us - /// whether this is an Objective-C selector, C++ operator-id name, - /// or special C++ name. + /// whether this is an Objective-C selector, C++ deduction guide, + /// C++ literal operator, or C++ using directive. uintptr_t Ptr = 0; - // Construct a declaration name from the name of a C++ constructor, - // destructor, or conversion function. - DeclarationName(DeclarationNameExtra *Name) - : Ptr(reinterpret_cast(Name)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra"); - Ptr |= StoredDeclarationNameExtra; - } - - /// Construct a declaration name from a raw pointer. - DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {} - - /// getStoredNameKind - Return the kind of object that is stored in - /// Ptr. StoredNameKind getStoredNameKind() const { return static_cast(Ptr & PtrMask); } - /// getExtra - Get the "extra" information associated with this - /// multi-argument selector or C++ special name. - DeclarationNameExtra *getExtra() const { - assert(getStoredNameKind() == StoredDeclarationNameExtra && - "Declaration name does not store an Extra structure"); - return reinterpret_cast(Ptr & ~PtrMask); - } - - /// getAsCXXSpecialName - If the stored pointer is actually a - /// CXXSpecialName, returns a pointer to it. Otherwise, returns - /// a NULL pointer. - CXXSpecialName *getAsCXXSpecialName() const { - NameKind Kind = getNameKind(); - if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName) - return reinterpret_cast(getExtra()); - return nullptr; - } - - /// If the stored pointer is actually a CXXDeductionGuideNameExtra, returns a - /// pointer to it. Otherwise, returns a NULL pointer. - CXXDeductionGuideNameExtra *getAsCXXDeductionGuideNameExtra() const { - if (getNameKind() == CXXDeductionGuideName) - return reinterpret_cast(getExtra()); - return nullptr; - } - - /// getAsCXXOperatorIdName - CXXOperatorIdName *getAsCXXOperatorIdName() const { - if (getNameKind() == CXXOperatorName) - return reinterpret_cast(getExtra()); - return nullptr; - } - - CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { - if (getNameKind() == CXXLiteralOperatorName) - return reinterpret_cast(getExtra()); - return nullptr; - } + void *getPtr() const { return reinterpret_cast(Ptr & ~PtrMask); } - /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer - /// for this name as a void pointer if it's not an identifier. - void *getFETokenInfoAsVoidSlow() const; + void setPtrAndKind(const void *P, StoredNameKind Kind) { + uintptr_t PAsInteger = reinterpret_cast(P); + assert((Kind & ~PtrMask) == 0 && + "Invalid StoredNameKind in setPtrAndKind!"); + assert((PAsInteger & PtrMask) == 0 && + "Improperly aligned pointer in setPtrAndKind!"); + Ptr = PAsInteger | Kind; + } + + /// Construct a declaration name from a DeclarationNameExtra. + DeclarationName(detail::DeclarationNameExtra *Name) { + setPtrAndKind(Name, StoredDeclarationNameExtra); + } + + /// Construct a declaration name from a CXXSpecialNameExtra. + DeclarationName(detail::CXXSpecialNameExtra *Name, + StoredNameKind StoredKind) { + assert(StoredKind == StoredCXXConstructorName || + StoredKind == StoredCXXDestructorName || + StoredKind == StoredCXXConversionFunctionName && + "Invalid StoredNameKind when constructing a DeclarationName" + " from a CXXSpecialNameExtra!"); + setPtrAndKind(Name, StoredKind); + } + + /// Construct a DeclarationName from a CXXOperatorIdName. + DeclarationName(detail::CXXOperatorIdName *Name) { + setPtrAndKind(Name, StoredCXXOperatorName); + } + + /// Assert that the stored pointer points to an IdentifierInfo and return it. + IdentifierInfo *castAsIdentifierInfo() const { + assert((getStoredNameKind() == StoredIdentifier) && + "DeclarationName does not store an IdentifierInfo!"); + return static_cast(getPtr()); + } + + /// Assert that the stored pointer points to a DeclarationNameExtra + /// and return it. + detail::DeclarationNameExtra *castAsExtra() const { + assert((getStoredNameKind() == StoredDeclarationNameExtra) && + "DeclarationName does not store an Extra structure!"); + return static_cast(getPtr()); + } + + /// Assert that the stored pointer points to a CXXSpecialNameExtra + /// and return it. + detail::CXXSpecialNameExtra *castAsCXXSpecialNameExtra() const { + assert(getStoredNameKind() == StoredCXXConstructorName || + getStoredNameKind() == StoredCXXDestructorName || + getStoredNameKind() == StoredCXXConversionFunctionName && + "DeclarationName does not store a CXXSpecialNameExtra!"); + return static_cast(getPtr()); + } + + /// Assert that the stored pointer points to a CXXOperatorIdName + /// and return it. + detail::CXXOperatorIdName *castAsCXXOperatorIdName() const { + assert(getStoredNameKind() == StoredCXXOperatorName && + "DeclarationName does not store a CXXOperatorIdName!"); + return static_cast(getPtr()); + } + + /// Assert that the stored pointer points to a CXXDeductionGuideNameExtra + /// and return it. + detail::CXXDeductionGuideNameExtra *castAsCXXDeductionGuideNameExtra() const { + assert(getNameKind() == CXXDeductionGuideName && + "DeclarationName does not store a CXXDeductionGuideNameExtra!"); + return static_cast(getPtr()); + } + + /// Assert that the stored pointer points to a CXXLiteralOperatorIdName + /// and return it. + detail::CXXLiteralOperatorIdName *castAsCXXLiteralOperatorIdName() const { + assert(getNameKind() == CXXLiteralOperatorName && + "DeclarationName does not store a CXXLiteralOperatorIdName!"); + return static_cast(getPtr()); + } + + /// Get and set the FETokenInfo in the less common cases where the + /// declaration name do not point to an identifier. + void *getFETokenInfoSlow() const; + void setFETokenInfoSlow(void *T); public: - /// DeclarationName - Used to create an empty selector. - DeclarationName() = default; + /// Construct an empty declaration name. + DeclarationName() { setPtrAndKind(nullptr, StoredIdentifier); } - // Construct a declaration name from an IdentifierInfo *. - DeclarationName(const IdentifierInfo *II) - : Ptr(reinterpret_cast(II)) { - assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); + /// Construct a declaration name from an IdentifierInfo *. + DeclarationName(const IdentifierInfo *II) { + setPtrAndKind(II, StoredIdentifier); } - // Construct a declaration name from an Objective-C selector. + /// Construct a declaration name from an Objective-C selector. DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) {} - /// getUsingDirectiveName - Return name for all using-directives. - static DeclarationName getUsingDirectiveName(); + /// Returns the name for all C++ using-directives. + static DeclarationName getUsingDirectiveName() { + // Single instance of DeclarationNameExtra for using-directive + static detail::DeclarationNameExtra UDirExtra( + detail::DeclarationNameExtra::CXXUsingDirective); + return DeclarationName(&UDirExtra); + } - // operator bool() - Evaluates true when this declaration name is - // non-empty. + /// Evaluates true when this declaration name is non-empty. explicit operator bool() const { - return ((Ptr & PtrMask) != 0) || - (reinterpret_cast(Ptr & ~PtrMask)); + return getPtr() || (getStoredNameKind() != StoredIdentifier); } /// Evaluates true when this declaration name is empty. - bool isEmpty() const { - return !*this; - } + bool isEmpty() const { return !*this; } /// Predicate functions for querying what type of name this is. bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } @@ -208,8 +381,19 @@ return getStoredNameKind() == StoredObjCOneArgSelector; } - /// getNameKind - Determine what kind of name this is. - NameKind getNameKind() const; + /// Determine what kind of name this is. + NameKind getNameKind() const { + // We rely on the fact that the first 7 NameKind and StoredNameKind + // have the same numerical value. This makes the usual case efficient. + StoredNameKind StoredKind = getStoredNameKind(); + if (StoredKind != StoredDeclarationNameExtra) + return static_cast(StoredKind); + // We have to consult DeclarationNameExtra. We rely on the fact that the + // enumeration values of ExtraKind correspond to the enumeration values of + // NameKind minus an offset of UncommonNameKindOffset. + unsigned ExtraKind = castAsExtra()->getKind(); + return static_cast(UncommonNameKindOffset + ExtraKind); + } /// Determines whether the name itself is dependent, e.g., because it /// involves a C++ type that is itself dependent. @@ -219,95 +403,128 @@ /// callee in a call expression with dependent arguments. bool isDependentName() const; - /// getNameAsString - Retrieve the human-readable string for this name. + /// Retrieve the human-readable string for this name. std::string getAsString() const; - /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in - /// this declaration name, or NULL if this declaration name isn't a - /// simple identifier. + /// Retrieve the IdentifierInfo * stored in this declaration name, + /// or null if this declaration name isn't a simple identifier. IdentifierInfo *getAsIdentifierInfo() const { if (isIdentifier()) - return reinterpret_cast(Ptr); + return castAsIdentifierInfo(); return nullptr; } - /// getAsOpaqueInteger - Get the representation of this declaration - /// name as an opaque integer. + /// Get the representation of this declaration name as an opaque integer. uintptr_t getAsOpaqueInteger() const { return Ptr; } - /// getAsOpaquePtr - Get the representation of this declaration name as - /// an opaque pointer. - void *getAsOpaquePtr() const { return reinterpret_cast(Ptr); } + /// Get the representation of this declaration name as an opaque pointer. + void *getAsOpaquePtr() const { return reinterpret_cast(Ptr); } + /// Get a declaration name from an opaque pointer returned by getAsOpaquePtr. static DeclarationName getFromOpaquePtr(void *P) { DeclarationName N; - N.Ptr = reinterpret_cast (P); + N.Ptr = reinterpret_cast(P); return N; } + /// Get a declaration name from an opaque integer + /// returned by getAsOpaqueInteger. static DeclarationName getFromOpaqueInteger(uintptr_t P) { DeclarationName N; N.Ptr = P; return N; } - /// getCXXNameType - If this name is one of the C++ names (of a - /// constructor, destructor, or conversion function), return the - /// type associated with that name. - QualType getCXXNameType() const; + /// If this name is one of the C++ names (of a constructor, destructor, + /// or conversion function), return the type associated with that name. + QualType getCXXNameType() const { + if (getStoredNameKind() == StoredCXXConstructorName || + getStoredNameKind() == StoredCXXDestructorName || + getStoredNameKind() == StoredCXXConversionFunctionName) { + assert(getPtr() && "getCXXNameType on a null DeclarationName!"); + return castAsCXXSpecialNameExtra()->Type; + } + return QualType(); + } /// If this name is the name of a C++ deduction guide, return the /// template associated with that name. - TemplateDecl *getCXXDeductionGuideTemplate() const; + TemplateDecl *getCXXDeductionGuideTemplate() const { + if (getNameKind() == CXXDeductionGuideName) { + assert(getPtr() && + "getCXXDeductionGuideTemplate on a null DeclarationName!"); + return castAsCXXDeductionGuideNameExtra()->Template; + } + return nullptr; + } - /// getCXXOverloadedOperator - If this name is the name of an - /// overloadable operator in C++ (e.g., @c operator+), retrieve the - /// kind of overloaded operator. - OverloadedOperatorKind getCXXOverloadedOperator() const; - - /// getCXXLiteralIdentifier - If this name is the name of a literal - /// operator, retrieve the identifier associated with it. - IdentifierInfo *getCXXLiteralIdentifier() const; + /// If this name is the name of an overloadable operator in C++ + /// (e.g., @c operator+), retrieve the kind of overloaded operator. + OverloadedOperatorKind getCXXOverloadedOperator() const { + if (getStoredNameKind() == StoredCXXOperatorName) { + assert(getPtr() && "getCXXOverloadedOperator on a null DeclarationName!"); + return castAsCXXOperatorIdName()->Kind; + } + return OO_None; + } + + /// If this name is the name of a literal operator, + /// retrieve the identifier associated with it. + IdentifierInfo *getCXXLiteralIdentifier() const { + if (getNameKind() == CXXLiteralOperatorName) { + assert(getPtr() && "getCXXLiteralIdentifier on a null DeclarationName!"); + return castAsCXXLiteralOperatorIdName()->ID; + } + return nullptr; + } - /// getObjCSelector - Get the Objective-C selector stored in this - /// declaration name. + /// Get the Objective-C selector stored in this declaration name. Selector getObjCSelector() const { assert((getNameKind() == ObjCZeroArgSelector || getNameKind() == ObjCOneArgSelector || - getNameKind() == ObjCMultiArgSelector || - Ptr == 0) && "Not a selector!"); + getNameKind() == ObjCMultiArgSelector || !getPtr()) && + "Not a selector!"); return Selector(Ptr); } - /// getFETokenInfo/setFETokenInfo - The language front-end is - /// allowed to associate arbitrary metadata with some kinds of - /// declaration names, including normal identifiers and C++ - /// constructors, destructors, and conversion functions. - template - T *getFETokenInfo() const { - if (const IdentifierInfo *Info = getAsIdentifierInfo()) - return Info->getFETokenInfo(); - return static_cast(getFETokenInfoAsVoidSlow()); + /// Get and set FETokenInfo. The language front-end is allowed to associate + /// arbitrary metadata with some kinds of declaration names, including normal + /// identifiers and C++ constructors, destructors, and conversion functions. + void *getFETokenInfo() const { + assert(getPtr() && "getFETokenInfo on an empty DeclarationName!"); + if (getStoredNameKind() == StoredIdentifier) + return castAsIdentifierInfo()->getFETokenInfo(); + return getFETokenInfoSlow(); + } + + void setFETokenInfo(void *T) { + assert(getPtr() && "setFETokenInfo on an empty DeclarationName!"); + if (getStoredNameKind() == StoredIdentifier) + castAsIdentifierInfo()->setFETokenInfo(T); + else + setFETokenInfoSlow(T); } - void setFETokenInfo(void *T); - - /// operator== - Determine whether the specified names are identical.. + /// Determine whether the specified names are identical. friend bool operator==(DeclarationName LHS, DeclarationName RHS) { return LHS.Ptr == RHS.Ptr; } - /// operator!= - Determine whether the specified names are different. + /// Determine whether the specified names are different. friend bool operator!=(DeclarationName LHS, DeclarationName RHS) { return LHS.Ptr != RHS.Ptr; } static DeclarationName getEmptyMarker() { - return DeclarationName(uintptr_t(-1)); + DeclarationName Name; + Name.Ptr = uintptr_t(-1); + return Name; } static DeclarationName getTombstoneMarker() { - return DeclarationName(uintptr_t(-2)); + DeclarationName Name; + Name.Ptr = uintptr_t(-2); + return Name; } static int compare(DeclarationName LHS, DeclarationName RHS); @@ -343,105 +560,47 @@ return DeclarationName::compare(LHS, RHS) >= 0; } -/// CXXSpecialName - Records the type associated with one of the -/// "special" kinds of declaration names in C++, e.g., constructors, -/// destructors, and conversion functions. -class CXXSpecialName : public DeclarationNameExtra, - public llvm::FoldingSetNode { -public: - /// Type - The type associated with this declaration name. - QualType Type; - - /// FETokenInfo - Extra information associated with this declaration - /// name that can be used by the front end. All bits are really needed - /// so it is not possible to stash something in the low order bits. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &ID) { - ID.AddInteger(ExtraKindOrNumArgs); - ID.AddPointer(Type.getAsOpaquePtr()); - } -}; - -/// Contains extra information for the name of a C++ deduction guide. -class CXXDeductionGuideNameExtra : public DeclarationNameExtra, - public llvm::FoldingSetNode { -public: - /// The template named by the deduction guide. - TemplateDecl *Template; - - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. All bits are really needed - /// so it is not possible to stash something in the low order bits. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &ID) { ID.AddPointer(Template); } -}; - -/// CXXOperatorIdName - Contains extra information for the name of an -/// overloaded operator in C++, such as "operator+. -class CXXOperatorIdName : public DeclarationNameExtra { -public: - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. All bits are really needed - /// so it is not possible to stash something in the low order bits. - void *FETokenInfo; -}; - -/// CXXLiteralOperatorName - Contains the actual identifier that makes up the -/// name. -/// -/// This identifier is stored here rather than directly in DeclarationName so as -/// to allow Objective-C selectors, which are about a million times more common, -/// to consume minimal memory. -class CXXLiteralOperatorIdName : public DeclarationNameExtra, - public llvm::FoldingSetNode { -public: - IdentifierInfo *ID; - - /// FETokenInfo - Extra information associated with this operator - /// name that can be used by the front end. All bits are really needed - /// so it is not possible to stash something in the low order bits. - void *FETokenInfo; - - void Profile(llvm::FoldingSetNodeID &FSID) { FSID.AddPointer(ID); } -}; - -/// DeclarationNameTable - Used to store and retrieve DeclarationName +/// DeclarationNameTable is used to store and retrieve DeclarationName /// instances for the various kinds of declaration names, e.g., normal /// identifiers, C++ constructor names, etc. This class contains /// uniqued versions of each of the C++ special names, which can be /// retrieved using its member functions (e.g., getCXXConstructorName). class DeclarationNameTable { - /// Used to allocate elements in the FoldingSets and - /// in the array of CXXOperatorIdName below. + /// Used to allocate elements in the FoldingSets below. const ASTContext &Ctx; - /// Manage the uniqued CXXSpecialName, which contain extra information - /// for the "special" kinds of declaration names in C++ such as constructors, - /// destructors and conversion functions. getCXXConstructorName, - /// getCXXDestructorName, getCXXConversionFunctionName, and getCXXSpecialName - /// can be used to obtain a DeclarationName from the corresponding type. - llvm::FoldingSet CXXSpecialNames; + /// Manage the uniqued CXXSpecialNameExtra representing C++ constructors. + /// getCXXConstructorName and getCXXSpecialName can be used to obtain + /// a DeclarationName from the corresponding type of the constructor. + llvm::FoldingSet CXXConstructorNames; + + /// Manage the uniqued CXXSpecialNameExtra representing C++ destructors. + /// getCXXDestructorName and getCXXSpecialName can be used to obtain + /// a DeclarationName from the corresponding type of the destructor. + llvm::FoldingSet CXXDestructorNames; + + /// Manage the uniqued CXXSpecialNameExtra representing C++ conversion + /// functions. getCXXConversionFunctionName and getCXXSpecialName can be + /// used to obtain a DeclarationName from the corresponding type of the + /// conversion function. + llvm::FoldingSet CXXConversionFunctionNames; /// Manage the uniqued CXXOperatorIdName, which contain extra information /// for the name of overloaded C++ operators. getCXXOperatorName /// can be used to obtain a DeclarationName from the operator kind. - /// This points to the first element of an array of NUM_OVERLOADED_OPERATORS - /// CXXOperatorIdName which is constructed by DeclarationNameTable. - CXXOperatorIdName *CXXOperatorNames; + detail::CXXOperatorIdName CXXOperatorNames[NUM_OVERLOADED_OPERATORS]; /// Manage the uniqued CXXLiteralOperatorIdName, which contain extra /// information for the name of C++ literal operators. /// getCXXLiteralOperatorName can be used to obtain a DeclarationName /// from the corresponding IdentifierInfo. - llvm::FoldingSet CXXLiteralOperatorNames; + llvm::FoldingSet CXXLiteralOperatorNames; /// Manage the uniqued CXXDeductionGuideNameExtra, which contain /// extra information for the name of a C++ deduction guide. /// getCXXDeductionGuideName can be used to obtain a DeclarationName /// from the corresponding template declaration. - llvm::FoldingSet CXXDeductionGuideNames; + llvm::FoldingSet CXXDeductionGuideNames; public: DeclarationNameTable(const ASTContext &C); @@ -451,39 +610,38 @@ DeclarationNameTable &operator=(DeclarationNameTable &&) = delete; ~DeclarationNameTable() = default; - /// getIdentifier - Create a declaration name that is a simple - /// identifier. + /// Create a declaration name that is a simple identifier. DeclarationName getIdentifier(const IdentifierInfo *ID) { return DeclarationName(ID); } - /// getCXXConstructorName - Returns the name of a C++ constructor - /// for the given Type. + /// Returns the name of a C++ constructor for the given Type. DeclarationName getCXXConstructorName(CanQualType Ty); - /// getCXXDestructorName - Returns the name of a C++ destructor - /// for the given Type. + /// Returns the name of a C++ destructor for the given Type. DeclarationName getCXXDestructorName(CanQualType Ty); /// Returns the name of a C++ deduction guide for the given template. DeclarationName getCXXDeductionGuideName(TemplateDecl *TD); - /// getCXXConversionFunctionName - Returns the name of a C++ - /// conversion function for the given Type. + /// Returns the name of a C++ conversion function for the given Type. DeclarationName getCXXConversionFunctionName(CanQualType Ty); - /// getCXXSpecialName - Returns a declaration name for special kind - /// of C++ name, e.g., for a constructor, destructor, or conversion - /// function. + /// Returns a declaration name for special kind of C++ name, + /// e.g., for a constructor, destructor, or conversion function. + /// Kind must be one of: + /// * DeclarationName::CXXConstructorName, + /// * DeclarationName::CXXDestructorName or + /// * DeclarationName::CXXConversionFunctionName DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, CanQualType Ty); - /// getCXXOperatorName - Get the name of the overloadable C++ - /// operator corresponding to Op. - DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); + /// Get the name of the overloadable C++ operator corresponding to Op. + DeclarationName getCXXOperatorName(OverloadedOperatorKind Op) { + return DeclarationName(&CXXOperatorNames[Op]); + } - /// getCXXLiteralOperatorName - Get the name of the literal operator function - /// with II as the identifier. + /// Get the name of the literal operator function with II as the identifier. DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); }; Index: include/clang/Basic/IdentifierTable.h =================================================================== --- include/clang/Basic/IdentifierTable.h +++ include/clang/Basic/IdentifierTable.h @@ -34,6 +34,8 @@ namespace clang { +class DeclarationName; +class DeclarationNameTable; class IdentifierInfo; class LangOptions; class MultiKeywordSelector; @@ -42,12 +44,18 @@ /// A simple pair of identifier info and location. using IdentifierLocPair = std::pair; +/// IdentifierInfo and other related classes are aligned to +/// 8 bytes so that DeclarationName can use the lower 3 bits +/// of a pointer to one of these classes. +enum { IdentifierInfoAlignment = 8 }; + /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, /// is a language keyword, or if it is a front-end token of some sort (e.g. a /// variable or function name). The preprocessor keeps this information in a /// set, and all tok::identifier tokens have a pointer to one of these. -class IdentifierInfo { +/// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits. +class alignas(IdentifierInfoAlignment) IdentifierInfo { friend class IdentifierTable; // Front-end token ID or tok::identifier. @@ -308,10 +316,9 @@ /// language. bool isCPlusPlusKeyword(const LangOptions &LangOpts) const; - /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to - /// associate arbitrary metadata with this token. - template - T *getFETokenInfo() const { return static_cast(FETokenInfo); } + /// Get and set FETokenInfo. The language front-end is allowed to associate + /// arbitrary metadata with this token. + void *getFETokenInfo() const { return FETokenInfo; } void setFETokenInfo(void *T) { FETokenInfo = T; } /// Return true if the Preprocessor::HandleIdentifier must be called @@ -677,16 +684,22 @@ /// accounts for 78% of all selectors in Cocoa.h. class Selector { friend class Diagnostic; + friend class SelectorTable; // only the SelectorTable can create these + friend class DeclarationName; // and the AST's DeclarationName. enum IdentifierInfoFlag { - // Empty selector = 0. - ZeroArg = 0x1, - OneArg = 0x2, - MultiArg = 0x3, - ArgFlags = ZeroArg|OneArg + // Empty selector = 0. Note that these enumeration values must + // correspond to the enumeration values of DeclarationName::StoredNameKind + ZeroArg = 0x01, + OneArg = 0x02, + MultiArg = 0x07, + ArgFlags = 0x07 }; - // a pointer to the MultiKeywordSelector or IdentifierInfo. + /// A pointer to the MultiKeywordSelector or IdentifierInfo. We use the low + /// three bits of InfoPtr to store an IdentifierInfoFlag. Note that in any + /// case IdentifierInfo and MultiKeywordSelector are already aligned to + /// 8 bytes even on 32 bits archs because of DeclarationName. uintptr_t InfoPtr = 0; Selector(IdentifierInfo *II, unsigned nArgs) { @@ -721,13 +734,10 @@ static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel); public: - friend class SelectorTable; // only the SelectorTable can create these - friend class DeclarationName; // and the AST's DeclarationName. - /// The default ctor should only be used when creating data structures that /// will contain selectors. Selector() = default; - Selector(uintptr_t V) : InfoPtr(V) {} + explicit Selector(uintptr_t V) : InfoPtr(V) {} /// operator==/!= - Indicate whether the specified selectors are identical. bool operator==(Selector RHS) const { @@ -856,39 +866,68 @@ static std::string getPropertyNameFromSetterSelector(Selector Sel); }; -/// DeclarationNameExtra - Common base of the MultiKeywordSelector, -/// CXXSpecialName, and CXXOperatorIdName classes, all of which are -/// private classes that describe different kinds of names. -class DeclarationNameExtra { -public: - /// ExtraKind - The kind of "extra" information stored in the - /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of - /// how these enumerator values are used. +namespace detail { + +/// DeclarationNameExtra is used as a base of various uncommon special names. +/// This class is needed since DeclarationName has not enough space to store +/// the kind of every possible names. Therefore the kind of common names is +/// stored directly in DeclarationName, and the kind of uncommon names is +/// stored in DeclarationNameExtra. It is aligned to 8 bytes because +/// DeclarationName needs the lower 3 bits to store the kind of common names. +/// DeclarationNameExtra is tightly coupled to DeclarationName and any change +/// here is very likely to require changes in DeclarationName(Table). +class alignas(IdentifierInfoAlignment) DeclarationNameExtra { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; + +protected: + /// The kind of "extra" information stored in the DeclarationName. See + /// @c ExtraKindOrNumArgs for an explanation of how these enumerator values + /// are used. Note that DeclarationName depends on the numerical values + /// of the enumerators in this enum. See DeclarationName::StoredNameKind + /// for more info. enum ExtraKind { - CXXConstructor = 0, - CXXDestructor, - CXXConversionFunction, -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - CXXOperator##Name, -#include "clang/Basic/OperatorKinds.def" - CXXDeductionGuide, - CXXLiteralOperator, + CXXDeductionGuideName, + CXXLiteralOperatorName, CXXUsingDirective, - NUM_EXTRA_KINDS + ObjCMultiArgSelector }; - /// ExtraKindOrNumArgs - Either the kind of C++ special name or - /// operator-id (if the value is one of the CXX* enumerators of - /// ExtraKind), in which case the DeclarationNameExtra is also a - /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or - /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName, - /// it may be also name common to C++ using-directives (CXXUsingDirective), - /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of - /// arguments in the Objective-C selector, in which case the - /// DeclarationNameExtra is also a MultiKeywordSelector. + /// ExtraKindOrNumArgs has one of the following meaning: + /// * The kind of an uncommon C++ special name. This DeclarationNameExtra + /// is in this case in fact either a CXXDeductionGuideNameExtra or + /// a CXXLiteralOperatorIdName. + /// + /// * It may be also name common to C++ using-directives (CXXUsingDirective), + /// + /// * Otherwise it is ObjCMultiArgSelector+NumArgs, where NumArgs is + /// the number of arguments in the Objective-C selector, in which + /// case the DeclarationNameExtra is also a MultiKeywordSelector. unsigned ExtraKindOrNumArgs; + + DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {} + DeclarationNameExtra(unsigned NumArgs) + : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {} + + /// Return the corresponding ExtraKind. + ExtraKind getKind() const { + return static_cast(ExtraKindOrNumArgs > + (unsigned)ObjCMultiArgSelector + ? (unsigned)ObjCMultiArgSelector + : ExtraKindOrNumArgs); + } + + /// Return the number of arguments in an ObjC selector. Only valid when this + /// is indeed an ObjCMultiArgSelector. + unsigned getNumArgs() const { + assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector && + "getNumArgs called but this is not an ObjC selector!"); + return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector; + } }; +} // namespace detail + } // namespace clang namespace llvm { Index: lib/AST/DeclarationName.cpp =================================================================== --- lib/AST/DeclarationName.cpp +++ lib/AST/DeclarationName.cpp @@ -49,10 +49,12 @@ switch (LHS.getNameKind()) { case DeclarationName::Identifier: { - IdentifierInfo *LII = LHS.getAsIdentifierInfo(); - IdentifierInfo *RII = RHS.getAsIdentifierInfo(); - if (!LII) return RII ? -1 : 0; - if (!RII) return 1; + IdentifierInfo *LII = LHS.castAsIdentifierInfo(); + IdentifierInfo *RII = RHS.castAsIdentifierInfo(); + if (!LII) + return RII ? -1 : 0; + if (!RII) + return 1; return LII->getName().compare(RII->getName()); } @@ -66,15 +68,18 @@ if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector && RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) { return LHSSelector.getAsIdentifierInfo()->getName().compare( - RHSSelector.getAsIdentifierInfo()->getName()); + RHSSelector.getAsIdentifierInfo()->getName()); } unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { switch (LHSSelector.getNameForSlot(I).compare( - RHSSelector.getNameForSlot(I))) { - case -1: return -1; - case 1: return 1; - default: break; + RHSSelector.getNameForSlot(I))) { + case -1: + return -1; + case 1: + return 1; + default: + break; } } @@ -102,7 +107,7 @@ case DeclarationName::CXXLiteralOperatorName: return LHS.getCXXLiteralIdentifier()->getName().compare( - RHS.getCXXLiteralIdentifier()->getName()); + RHS.getCXXLiteralIdentifier()->getName()); case DeclarationName::CXXUsingDirective: return 0; @@ -131,25 +136,24 @@ } void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) { - DeclarationName &N = *this; - switch (N.getNameKind()) { + switch (getNameKind()) { case DeclarationName::Identifier: - if (const IdentifierInfo *II = N.getAsIdentifierInfo()) + if (const IdentifierInfo *II = getAsIdentifierInfo()) OS << II->getName(); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - N.getObjCSelector().print(OS); + getObjCSelector().print(OS); return; case DeclarationName::CXXConstructorName: - return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); case DeclarationName::CXXDestructorName: OS << '~'; - return printCXXConstructorDestructorName(N.getCXXNameType(), OS, Policy); + return printCXXConstructorDestructorName(getCXXNameType(), OS, Policy); case DeclarationName::CXXDeductionGuideName: OS << "getName(); + OS << "operator\"\"" << getCXXLiteralIdentifier()->getName(); return; case DeclarationName::CXXConversionFunctionName: { OS << "operator "; - QualType Type = N.getCXXNameType(); + QualType Type = getCXXNameType(); if (const RecordType *Rec = Type->getAs()) { OS << *Rec->getDecl(); return; @@ -209,46 +213,6 @@ } // namespace clang -DeclarationName::NameKind DeclarationName::getNameKind() const { - switch (getStoredNameKind()) { - case StoredIdentifier: return Identifier; - case StoredObjCZeroArgSelector: return ObjCZeroArgSelector; - case StoredObjCOneArgSelector: return ObjCOneArgSelector; - - case StoredDeclarationNameExtra: - switch (getExtra()->ExtraKindOrNumArgs) { - case DeclarationNameExtra::CXXConstructor: - return CXXConstructorName; - - case DeclarationNameExtra::CXXDestructor: - return CXXDestructorName; - - case DeclarationNameExtra::CXXDeductionGuide: - return CXXDeductionGuideName; - - case DeclarationNameExtra::CXXConversionFunction: - return CXXConversionFunctionName; - - case DeclarationNameExtra::CXXLiteralOperator: - return CXXLiteralOperatorName; - - case DeclarationNameExtra::CXXUsingDirective: - return CXXUsingDirective; - - default: - // Check if we have one of the CXXOperator* enumeration values. - if (getExtra()->ExtraKindOrNumArgs < - DeclarationNameExtra::CXXUsingDirective) - return CXXOperatorName; - - return ObjCMultiArgSelector; - } - } - - // Can't actually get here. - llvm_unreachable("This should be unreachable!"); -} - bool DeclarationName::isDependentName() const { QualType T = getCXXNameType(); if (!T.isNull() && T->isDependentType()) @@ -269,122 +233,56 @@ return OS.str(); } -QualType DeclarationName::getCXXNameType() const { - if (CXXSpecialName *CXXName = getAsCXXSpecialName()) - return CXXName->Type; - else - return QualType(); -} - -TemplateDecl *DeclarationName::getCXXDeductionGuideTemplate() const { - if (auto *Guide = getAsCXXDeductionGuideNameExtra()) - return Guide->Template; - return nullptr; -} - -OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { - if (CXXOperatorIdName *CXXOp = getAsCXXOperatorIdName()) { - unsigned value - = CXXOp->ExtraKindOrNumArgs - DeclarationNameExtra::CXXConversionFunction; - return static_cast(value); - } else { - return OO_None; - } -} - -IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const { - if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName()) - return CXXLit->ID; - else - return nullptr; -} - -void *DeclarationName::getFETokenInfoAsVoidSlow() const { +void *DeclarationName::getFETokenInfoSlow() const { switch (getNameKind()) { case Identifier: - llvm_unreachable("Handled by getFETokenInfo()"); - + llvm_unreachable("case Identifier already handled by getFETokenInfo!"); case CXXConstructorName: case CXXDestructorName: case CXXConversionFunctionName: - return getAsCXXSpecialName()->FETokenInfo; - - case CXXDeductionGuideName: - return getAsCXXDeductionGuideNameExtra()->FETokenInfo; - + return castAsCXXSpecialNameExtra()->FETokenInfo; case CXXOperatorName: - return getAsCXXOperatorIdName()->FETokenInfo; - + return castAsCXXOperatorIdName()->FETokenInfo; + case CXXDeductionGuideName: + return castAsCXXDeductionGuideNameExtra()->FETokenInfo; case CXXLiteralOperatorName: - return getAsCXXLiteralOperatorIdName()->FETokenInfo; - + return castAsCXXLiteralOperatorIdName()->FETokenInfo; default: - llvm_unreachable("Declaration name has no FETokenInfo"); + llvm_unreachable("DeclarationName has no FETokenInfo!"); } } -void DeclarationName::setFETokenInfo(void *T) { +void DeclarationName::setFETokenInfoSlow(void *T) { switch (getNameKind()) { case Identifier: - getAsIdentifierInfo()->setFETokenInfo(T); - break; - + llvm_unreachable("case Identifier already handled by setFETokenInfo!"); case CXXConstructorName: case CXXDestructorName: case CXXConversionFunctionName: - getAsCXXSpecialName()->FETokenInfo = T; + castAsCXXSpecialNameExtra()->FETokenInfo = T; break; - - case CXXDeductionGuideName: - getAsCXXDeductionGuideNameExtra()->FETokenInfo = T; - break; - case CXXOperatorName: - getAsCXXOperatorIdName()->FETokenInfo = T; + castAsCXXOperatorIdName()->FETokenInfo = T; + break; + case CXXDeductionGuideName: + castAsCXXDeductionGuideNameExtra()->FETokenInfo = T; break; - case CXXLiteralOperatorName: - getAsCXXLiteralOperatorIdName()->FETokenInfo = T; + castAsCXXLiteralOperatorIdName()->FETokenInfo = T; break; - default: - llvm_unreachable("Declaration name has no FETokenInfo"); + llvm_unreachable("DeclarationName has no FETokenInfo!"); } } -DeclarationName DeclarationName::getUsingDirectiveName() { - // Single instance of DeclarationNameExtra for using-directive - static const DeclarationNameExtra UDirExtra = - { DeclarationNameExtra::CXXUsingDirective }; - - uintptr_t Ptr = reinterpret_cast(&UDirExtra); - Ptr |= StoredDeclarationNameExtra; - - return DeclarationName(Ptr); -} - LLVM_DUMP_METHOD void DeclarationName::dump() const { llvm::errs() << *this << '\n'; } DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { // Initialize the overloaded operator names. - CXXOperatorNames = new (Ctx) CXXOperatorIdName[NUM_OVERLOADED_OPERATORS]; - for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) { - CXXOperatorNames[Op].ExtraKindOrNumArgs - = Op + DeclarationNameExtra::CXXConversionFunction; - CXXOperatorNames[Op].FETokenInfo = nullptr; - } -} - -DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConstructorName, - Ty.getUnqualifiedType()); -} - -DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXDestructorName, - Ty.getUnqualifiedType()); + for (unsigned Op = 0; Op < NUM_OVERLOADED_OPERATORS; ++Op) + CXXOperatorNames[Op].Kind = static_cast(Op); } DeclarationName @@ -398,65 +296,72 @@ if (auto *Name = CXXDeductionGuideNames.FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName(Name); - auto *Name = new (Ctx) CXXDeductionGuideNameExtra; - Name->ExtraKindOrNumArgs = DeclarationNameExtra::CXXDeductionGuide; - Name->Template = Template; - Name->FETokenInfo = nullptr; - + auto *Name = new (Ctx) detail::CXXDeductionGuideNameExtra(Template); CXXDeductionGuideNames.InsertNode(Name, InsertPos); return DeclarationName(Name); } +DeclarationName DeclarationNameTable::getCXXConstructorName(CanQualType Ty) { + // The type of constructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ constructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXConstructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConstructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConstructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConstructorName}; +} + +DeclarationName DeclarationNameTable::getCXXDestructorName(CanQualType Ty) { + // The type of destructors is unqualified. + Ty = Ty.getUnqualifiedType(); + // Do we already have this C++ destructor name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = CXXDestructorNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXDestructorName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXDestructorNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXDestructorName}; +} + DeclarationName DeclarationNameTable::getCXXConversionFunctionName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty); + // Do we already have this C++ conversion function name ? + llvm::FoldingSetNodeID ID; + ID.AddPointer(Ty.getAsOpaquePtr()); + void *InsertPos = nullptr; + if (auto *Name = + CXXConversionFunctionNames.FindNodeOrInsertPos(ID, InsertPos)) + return {Name, DeclarationName::StoredCXXConversionFunctionName}; + + // We have to create it. + auto *SpecialName = new (Ctx) detail::CXXSpecialNameExtra(Ty); + CXXConversionFunctionNames.InsertNode(SpecialName, InsertPos); + return {SpecialName, DeclarationName::StoredCXXConversionFunctionName}; } DeclarationName DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, CanQualType Ty) { - assert(Kind >= DeclarationName::CXXConstructorName && - Kind <= DeclarationName::CXXConversionFunctionName && - "Kind must be a C++ special name kind"); - - DeclarationNameExtra::ExtraKind EKind; switch (Kind) { case DeclarationName::CXXConstructorName: - EKind = DeclarationNameExtra::CXXConstructor; - assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified"); - break; + return getCXXConstructorName(Ty); case DeclarationName::CXXDestructorName: - EKind = DeclarationNameExtra::CXXDestructor; - assert(!Ty.hasQualifiers() && "Destructor type must be unqualified"); - break; + return getCXXDestructorName(Ty); case DeclarationName::CXXConversionFunctionName: - EKind = DeclarationNameExtra::CXXConversionFunction; - break; + return getCXXConversionFunctionName(Ty); default: - return DeclarationName(); + llvm_unreachable("Invalid kind in getCXXSpecialName!"); } - - // Unique selector, to guarantee there is one per name. - llvm::FoldingSetNodeID ID; - ID.AddInteger(EKind); - ID.AddPointer(Ty.getAsOpaquePtr()); - - void *InsertPos = nullptr; - if (CXXSpecialName *Name = CXXSpecialNames.FindNodeOrInsertPos(ID, InsertPos)) - return DeclarationName(Name); - - CXXSpecialName *SpecialName = new (Ctx) CXXSpecialName; - SpecialName->ExtraKindOrNumArgs = EKind; - SpecialName->Type = Ty; - SpecialName->FETokenInfo = nullptr; - - CXXSpecialNames.InsertNode(SpecialName, InsertPos); - return DeclarationName(SpecialName); -} - -DeclarationName -DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) { - return DeclarationName(&CXXOperatorNames[(unsigned)Op]); } DeclarationName @@ -465,15 +370,10 @@ ID.AddPointer(II); void *InsertPos = nullptr; - if (CXXLiteralOperatorIdName *Name = - CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos)) - return DeclarationName (Name); - - CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; - LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; - LiteralName->ID = II; - LiteralName->FETokenInfo = nullptr; + if (auto *Name = CXXLiteralOperatorNames.FindNodeOrInsertPos(ID, InsertPos)) + return DeclarationName(Name); + auto *LiteralName = new (Ctx) detail::CXXLiteralOperatorIdName(II); CXXLiteralOperatorNames.InsertNode(LiteralName, InsertPos); return DeclarationName(LiteralName); } Index: lib/Basic/IdentifierTable.cpp =================================================================== --- lib/Basic/IdentifierTable.cpp +++ lib/Basic/IdentifierTable.cpp @@ -382,24 +382,23 @@ namespace clang { -/// MultiKeywordSelector - One of these variable length records is kept for each +/// One of these variable length records is kept for each /// selector containing more than one keyword. We use a folding set /// to unique aggregate names (keyword selectors in ObjC parlance). Access to /// this class is provided strictly through Selector. -class MultiKeywordSelector - : public DeclarationNameExtra, public llvm::FoldingSetNode { - MultiKeywordSelector(unsigned nKeys) { - ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys; - } +class alignas(IdentifierInfoAlignment) MultiKeywordSelector + : public detail::DeclarationNameExtra, + public llvm::FoldingSetNode { + MultiKeywordSelector(unsigned nKeys) : DeclarationNameExtra(nKeys) {} public: // Constructor for keyword selectors. - MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) { + MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) + : DeclarationNameExtra(nKeys) { assert((nKeys > 1) && "not a multi-keyword selector"); - ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys; // Fill in the trailing keyword array. - IdentifierInfo **KeyInfo = reinterpret_cast(this+1); + IdentifierInfo **KeyInfo = reinterpret_cast(this + 1); for (unsigned i = 0; i != nKeys; ++i) KeyInfo[i] = IIV[i]; } @@ -407,16 +406,16 @@ // getName - Derive the full selector name and return it. std::string getName() const; - unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; } + using DeclarationNameExtra::getNumArgs; using keyword_iterator = IdentifierInfo *const *; keyword_iterator keyword_begin() const { - return reinterpret_cast(this+1); + return reinterpret_cast(this + 1); } keyword_iterator keyword_end() const { - return keyword_begin()+getNumArgs(); + return keyword_begin() + getNumArgs(); } IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const { @@ -424,8 +423,8 @@ return keyword_begin()[i]; } - static void Profile(llvm::FoldingSetNodeID &ID, - keyword_iterator ArgTys, unsigned NumArgs) { + static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, + unsigned NumArgs) { ID.AddInteger(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) ID.AddPointer(ArgTys[i]); @@ -462,7 +461,7 @@ StringRef Selector::getNameForSlot(unsigned int argIndex) const { IdentifierInfo *II = getIdentifierInfoForSlot(argIndex); - return II? II->getName() : StringRef(); + return II ? II->getName() : StringRef(); } std::string MultiKeywordSelector::getName() const { Index: lib/Sema/IdentifierResolver.cpp =================================================================== --- lib/Sema/IdentifierResolver.cpp +++ lib/Sema/IdentifierResolver.cpp @@ -147,7 +147,7 @@ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { Name.setFETokenInfo(D); @@ -172,7 +172,7 @@ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { AddDecl(D); @@ -213,7 +213,7 @@ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) updatingIdentifier(*II); - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); assert(Ptr && "Didn't find this decl on its identifier's chain!"); @@ -232,7 +232,7 @@ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) readingIdentifier(*II); - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) return end(); if (isDeclPtr(Ptr)) @@ -304,7 +304,7 @@ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) readingIdentifier(*II); - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); if (!Ptr) { Name.setFETokenInfo(D); @@ -397,7 +397,7 @@ /// It creates a new IdDeclInfo if one was not created before for this id. IdentifierResolver::IdDeclInfo & IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { - void *Ptr = Name.getFETokenInfo(); + void *Ptr = Name.getFETokenInfo(); if (Ptr) return *toIdDeclInfo(Ptr); @@ -415,7 +415,7 @@ void IdentifierResolver::iterator::incrementSlowCase() { NamedDecl *D = **this; - void *InfoPtr = D->getDeclName().getFETokenInfo(); + void *InfoPtr = D->getDeclName().getFETokenInfo(); assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); IdDeclInfo *Info = toIdDeclInfo(InfoPtr); Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -908,7 +908,7 @@ (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) || II.hasRevertedTokenIDToIdentifier() || (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) && - II.getFETokenInfo()); + II.getFETokenInfo()); } static bool readBit(unsigned &Bits) { Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -3574,7 +3574,7 @@ II->isPoisoned() || (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) || II->hasRevertedTokenIDToIdentifier() || - (NeedDecls && II->getFETokenInfo())) + (NeedDecls && II->getFETokenInfo())) return true; return false;