#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"
class ASTContext;
template <typename> 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;
using CanQualType = CanQual<Type>;
-/// 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<CXXSpecialName>
+/// 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());
+ }
+};
+
+/// 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;
- static const unsigned NumNameKinds = CXXUsingDirective + 1;
+ /// The template named by the deduction guide.
+ TemplateDecl *Template;
-private:
+ /// 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
+ };
+
+ 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
};
- /// Ptr - The lowest two bits are used to express what kind of name
- /// we're actually storing, using the values of NameKind. Depending
+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:
///
/// 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<uintptr_t>(Name)) {
- assert((Ptr & PtrMask) == 0 && "Improperly aligned DeclarationNameExtra");
- Ptr |= StoredDeclarationNameExtra;
+ StoredNameKind getStoredNameKind() const {
+ return static_cast<StoredNameKind>(Ptr & PtrMask);
}
- /// Construct a declaration name from a raw pointer.
- DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {}
+ void *getPtr() const { return reinterpret_cast<void *>(Ptr & ~PtrMask); }
- /// getStoredNameKind - Return the kind of object that is stored in
- /// Ptr.
- StoredNameKind getStoredNameKind() const {
- return static_cast<StoredNameKind>(Ptr & PtrMask);
+ void setPtrAndKind(const void *P, StoredNameKind Kind) {
+ uintptr_t PAsInteger = reinterpret_cast<uintptr_t>(P);
+ assert((Kind & ~PtrMask) == 0 &&
+ "Invalid StoredNameKind in setPtrAndKind!");
+ assert((PAsInteger & PtrMask) == 0 &&
+ "Improperly aligned pointer in setPtrAndKind!");
+ Ptr = PAsInteger | Kind;
}
- /// 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<DeclarationNameExtra *>(Ptr & ~PtrMask);
+ /// Construct a declaration name from a DeclarationNameExtra.
+ DeclarationName(detail::DeclarationNameExtra *Name) {
+ setPtrAndKind(Name, StoredDeclarationNameExtra);
}
- /// 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<CXXSpecialName *>(getExtra());
- return nullptr;
+ /// 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);
}
- /// 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<CXXDeductionGuideNameExtra *>(getExtra());
- return nullptr;
+ /// Construct a DeclarationName from a CXXOperatorIdName.
+ DeclarationName(detail::CXXOperatorIdName *Name) {
+ setPtrAndKind(Name, StoredCXXOperatorName);
}
- /// getAsCXXOperatorIdName
- CXXOperatorIdName *getAsCXXOperatorIdName() const {
- if (getNameKind() == CXXOperatorName)
- return reinterpret_cast<CXXOperatorIdName *>(getExtra());
- return nullptr;
+ /// 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<IdentifierInfo *>(getPtr());
}
- CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
- if (getNameKind() == CXXLiteralOperatorName)
- return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra());
- return nullptr;
+ /// 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<detail::DeclarationNameExtra *>(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<detail::CXXSpecialNameExtra *>(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<detail::CXXOperatorIdName *>(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<detail::CXXDeductionGuideNameExtra *>(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<detail::CXXLiteralOperatorIdName *>(getPtr());
}
- /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
- /// for this name as a void pointer if it's not an identifier.
- void *getFETokenInfoAsVoidSlow() const;
+ /// 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<uintptr_t>(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<IdentifierInfo *>(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; }
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<NameKind>(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<NameKind>(UncommonNameKindOffset + ExtraKind);
+ }
/// Determines whether the name itself is dependent, e.g., because it
/// involves a C++ type that is itself dependent.
/// 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<IdentifierInfo *>(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<void*>(Ptr); }
+ /// Get the representation of this declaration name as an opaque pointer.
+ void *getAsOpaquePtr() const { return reinterpret_cast<void *>(Ptr); }
+ /// Get a declaration name from an opaque pointer returned by getAsOpaquePtr.
static DeclarationName getFromOpaquePtr(void *P) {
DeclarationName N;
- N.Ptr = reinterpret_cast<uintptr_t> (P);
+ N.Ptr = reinterpret_cast<uintptr_t>(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;
+ /// 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;
+ }
- /// 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 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<typename T>
- T *getFETokenInfo() const {
- if (const IdentifierInfo *Info = getAsIdentifierInfo())
- return Info->getFETokenInfo<T>();
- return static_cast<T*>(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);
+ void setFETokenInfo(void *T) {
+ assert(getPtr() && "setFETokenInfo on an empty DeclarationName!");
+ if (getStoredNameKind() == StoredIdentifier)
+ castAsIdentifierInfo()->setFETokenInfo(T);
+ else
+ setFETokenInfoSlow(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);
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<CXXSpecialName> 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<detail::CXXSpecialNameExtra> 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<detail::CXXSpecialNameExtra> 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<detail::CXXSpecialNameExtra> 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<CXXLiteralOperatorIdName> CXXLiteralOperatorNames;
+ llvm::FoldingSet<detail::CXXLiteralOperatorIdName> 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<CXXDeductionGuideNameExtra> CXXDeductionGuideNames;
+ llvm::FoldingSet<detail::CXXDeductionGuideNameExtra> CXXDeductionGuideNames;
public:
DeclarationNameTable(const ASTContext &C);
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);
};
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());
}
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;
}
}
case DeclarationName::CXXLiteralOperatorName:
return LHS.getCXXLiteralIdentifier()->getName().compare(
- RHS.getCXXLiteralIdentifier()->getName());
+ RHS.getCXXLiteralIdentifier()->getName());
case DeclarationName::CXXUsingDirective:
return 0;
}
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 << "<deduction guide for ";
return;
case DeclarationName::CXXOperatorName: {
- static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
- nullptr,
-#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
- Spelling,
+ static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
+ nullptr,
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ Spelling,
#include "clang/Basic/OperatorKinds.def"
};
- const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
+ const char *OpName = OperatorNames[getCXXOverloadedOperator()];
assert(OpName && "not an overloaded operator");
OS << "operator";
}
case DeclarationName::CXXLiteralOperatorName:
- OS << "operator\"\"" << N.getCXXLiteralIdentifier()->getName();
+ OS << "operator\"\"" << getCXXLiteralIdentifier()->getName();
return;
case DeclarationName::CXXConversionFunctionName: {
OS << "operator ";
- QualType Type = N.getCXXNameType();
+ QualType Type = getCXXNameType();
if (const RecordType *Rec = Type->getAs<RecordType>()) {
OS << *Rec->getDecl();
return;
} // 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())
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<OverloadedOperatorKind>(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<uintptr_t>(&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<OverloadedOperatorKind>(Op);
}
DeclarationName
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
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);
}