This revision was automatically updated to reflect the committed changes.
Closed by commit rC342729: [AST] Various optimizations + refactoring in 
DeclarationName(Table) (authored by brunoricci, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D52267

Files:
  include/clang/AST/DeclarationName.h
  include/clang/Basic/IdentifierTable.h
  lib/AST/DeclarationName.cpp
  lib/Basic/IdentifierTable.cpp
  lib/Sema/IdentifierResolver.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTWriter.cpp

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,65 +33,195 @@
 
 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;
 class UsingDirectiveDecl;
 
 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());
+  }
+};
 
-  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<uintptr_t>(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<StoredNameKind>(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<DeclarationNameExtra *>(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<CXXSpecialName *>(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<CXXDeductionGuideNameExtra *>(getExtra());
-    return nullptr;
-  }
-
-  /// getAsCXXOperatorIdName
-  CXXOperatorIdName *getAsCXXOperatorIdName() const {
-    if (getNameKind() == CXXOperatorName)
-      return reinterpret_cast<CXXOperatorIdName *>(getExtra());
-    return nullptr;
-  }
-
-  CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
-    if (getNameKind() == CXXLiteralOperatorName)
-      return reinterpret_cast<CXXLiteralOperatorIdName *>(getExtra());
-    return nullptr;
-  }
+  void *getPtr() const { return reinterpret_cast<void *>(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<uintptr_t>(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<IdentifierInfo *>(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<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());
+  }
+
+  /// 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; }
@@ -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<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.
@@ -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<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;
-
-  /// 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<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) {
+    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<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);
@@ -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,20 +34,28 @@
 
 namespace clang {
 
+class DeclarationName;
+class DeclarationNameTable;
 class IdentifierInfo;
 class LangOptions;
 class MultiKeywordSelector;
 class SourceLocation;
 
 /// A simple pair of identifier info and location.
 using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
 
+/// 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<typename T>
-  T *getFETokenInfo() const { return static_cast<T*>(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<ExtraKind>(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,40 +136,39 @@
 }
 
 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 ";
     getCXXDeductionGuideTemplate()->getDeclName().print(OS, Policy);
     OS << '>';
     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";
@@ -175,12 +179,12 @@
   }
 
   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;
@@ -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<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
@@ -398,82 +296,84 @@
   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
 DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
   llvm::FoldingSetNodeID ID;
   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/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>();
+  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>();
+  void *Ptr = Name.getFETokenInfo();
 
   if (!Ptr) {
     AddDecl(D);
@@ -213,7 +213,7 @@
   if (IdentifierInfo *II = Name.getAsIdentifierInfo())
     updatingIdentifier(*II);
 
-  void *Ptr = Name.getFETokenInfo<void>();
+  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>();
+  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>();
+  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>();
+  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>();
+  void *InfoPtr = D->getDeclName().getFETokenInfo();
   assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
   IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
 
Index: lib/Basic/IdentifierTable.cpp
===================================================================
--- lib/Basic/IdentifierTable.cpp
+++ lib/Basic/IdentifierTable.cpp
@@ -382,50 +382,49 @@
 
 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<IdentifierInfo **>(this+1);
+    IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this + 1);
     for (unsigned i = 0; i != nKeys; ++i)
       KeyInfo[i] = IIV[i];
   }
 
   // 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<keyword_iterator>(this+1);
+    return reinterpret_cast<keyword_iterator>(this + 1);
   }
 
   keyword_iterator keyword_end() const {
-    return keyword_begin()+getNumArgs();
+    return keyword_begin() + getNumArgs();
   }
 
   IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
     assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
     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/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<void>()))
+        (NeedDecls && II->getFETokenInfo()))
       return true;
 
     return false;
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<void>());
+          II.getFETokenInfo());
 }
 
 static bool readBit(unsigned &Bits) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to