From 2e1cd4264d363ca869bf37ef160902f211d21b8c Mon Sep 17 00:00:00 2001
From: Douglas Gregor <dgregor@apple.com>
Date: Mon, 17 Nov 2008 14:58:09 +0000
Subject: [PATCH] Introduction the DeclarationName class, as a single, general
 method of representing the names of declarations in the C family of
 languages. DeclarationName is used in NamedDecl to store the name of the
 declaration (naturally), and ObjCMethodDecl is now a NamedDecl.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59441 91177308-0d34-0410-b5e6-96231b3b80d8
---
 Driver/RewriteBlocks.cpp              |  11 +-
 Driver/RewriteObjC.cpp                |  40 ++--
 docs/InternalsManual.html             | 104 ++++++++-
 include/clang/AST/ASTContext.h        |   5 +-
 include/clang/AST/Decl.h              |  63 ++++--
 include/clang/AST/DeclBase.h          |   2 +-
 include/clang/AST/DeclCXX.h           |  63 ++----
 include/clang/AST/DeclObjC.h          |  11 +-
 include/clang/AST/DeclarationName.h   | 294 ++++++++++++++++++++++++++
 include/clang/Basic/IdentifierTable.h |  39 +++-
 include/clang/Lex/Preprocessor.h      |   4 +-
 lib/AST/ASTContext.cpp                |   9 +-
 lib/AST/CMakeLists.txt                |   1 +
 lib/AST/Decl.cpp                      |  44 +++-
 lib/AST/DeclCXX.cpp                   |  62 ++----
 lib/AST/DeclObjC.cpp                  |   4 +-
 lib/AST/DeclSerialization.cpp         |  54 ++++-
 lib/AST/DeclarationName.cpp           | 166 +++++++++++++++
 lib/AST/StmtDumper.cpp                |  16 +-
 lib/Basic/IdentifierTable.cpp         |  22 +-
 lib/CodeGen/CGDebugInfo.cpp           |  11 +-
 lib/CodeGen/CGDecl.cpp                |   4 +-
 lib/CodeGen/CGObjCGNU.cpp             |  10 +-
 lib/CodeGen/CGObjCMac.cpp             |   6 +-
 lib/CodeGen/CodeGenFunction.cpp       |   2 +-
 lib/Sema/SemaDecl.cpp                 |  20 +-
 lib/Sema/SemaDeclCXX.cpp              |  18 +-
 lib/Sema/SemaDeclObjC.cpp             |   5 +-
 lib/Sema/SemaOverload.cpp             |   2 +-
 29 files changed, 890 insertions(+), 202 deletions(-)
 create mode 100644 include/clang/AST/DeclarationName.h
 create mode 100644 lib/AST/DeclarationName.cpp

diff --git a/Driver/RewriteBlocks.cpp b/Driver/RewriteBlocks.cpp
index d8e347fafba..535915344c6 100644
--- a/Driver/RewriteBlocks.cpp
+++ b/Driver/RewriteBlocks.cpp
@@ -618,7 +618,7 @@ void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart,
 
 void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
-  const char *FuncName = FD->getName();
+  const char *FuncName = FD->getIdentifierName();
   
   SynthesizeBlockLiterals(FunLocStart, FuncName);
 }
@@ -675,13 +675,13 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
   const BlockPointerType *CPT = 0;
   
   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
-    closureName = DRE->getDecl()->getName();
+    closureName = DRE->getDecl()->getIdentifierName();
     CPT = DRE->getType()->getAsBlockPointerType();
   } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
-    closureName = CDRE->getDecl()->getName();
+    closureName = CDRE->getDecl()->getIdentifierName();
     CPT = CDRE->getType()->getAsBlockPointerType();
   } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
-    closureName = MExpr->getMemberDecl()->getName();
+    closureName = MExpr->getMemberDecl()->getIdentifierName();
     CPT = MExpr->getType()->getAsBlockPointerType();
   } else {
     assert(1 && "RewriteBlockClass: Bad type");
@@ -1109,7 +1109,8 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) {
           std::string Init = SynthesizeBlockInitExpr(CBE, VD);
           // Do the rewrite, using S.size() which contains the rewritten size.
           ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
-          SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
+          SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), 
+                                  VD->getIdentifierName());
         } else if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) {
           RewriteCastExpr(CE);
         }
diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp
index 2903f998a05..69aedcc2dd8 100644
--- a/Driver/RewriteObjC.cpp
+++ b/Driver/RewriteObjC.cpp
@@ -506,7 +506,7 @@ void RewriteObjC::HandleTopLevelDecl(Decl *D) {
     RewriteFunctionDecl(FD);
   } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
     // declared in <Foundation/NSString.h>
-    if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) {
+    if (strcmp(FVD->getIdentifierName(), "_NSConstantStringClassReference") == 0) {
       ConstantStringClassReference = FVD;
       return;
     }
@@ -1088,13 +1088,13 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
     elementTypeAsString = ElementType.getAsString();
     buf += elementTypeAsString;
     buf += " ";
-    elementName = D->getName();
+    elementName = D->getIdentifierName();
     buf += elementName;
     buf += ";\n\t";
   }
   else {
     DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
-    elementName = DR->getDecl()->getName();
+    elementName = DR->getDecl()->getIdentifierName();
     elementTypeAsString 
       = cast<ValueDecl>(DR->getDecl())->getType().getAsString();
   }
@@ -1694,7 +1694,7 @@ void RewriteObjC::SynthGetProtocolFunctionDecl() {
 
 void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
   // declared in <objc/objc.h>
-  if (strcmp(FD->getName(), "sel_registerName") == 0) {
+  if (strcmp(FD->getIdentifierName(), "sel_registerName") == 0) {
     SelGetUidFunctionDecl = FD;
     return;
   }
@@ -2299,8 +2299,8 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
   // Create a call to objc_getProtocol("ProtocolName").
   llvm::SmallVector<Expr*, 8> ProtoExprs;
   QualType argType = Context->getPointerType(Context->CharTy);
-  ProtoExprs.push_back(new StringLiteral(Exp->getProtocol()->getName(),
-                                       strlen(Exp->getProtocol()->getName()),
+  ProtoExprs.push_back(new StringLiteral(Exp->getProtocol()->getIdentifierName(),
+                                       strlen(Exp->getProtocol()->getIdentifierName()),
                                        false, argType, SourceLocation(),
                                        SourceLocation()));
   CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl,
@@ -2343,7 +2343,8 @@ bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
 void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
                                                std::string &Result) {
   assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
-  assert(CDecl->getName() && "Name missing in SynthesizeObjCInternalStruct");
+  assert(CDecl->getIdentifierName() && 
+         "Name missing in SynthesizeObjCInternalStruct");
   // Do not synthesize more than once.
   if (ObjCSynthesizedStructs.count(CDecl))
     return;
@@ -2922,15 +2923,15 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
   
   // Build _objc_method_list for class's instance methods if needed
   RewriteObjCMethodsMetaData(IDecl->instmeth_begin(), IDecl->instmeth_end(), 
-                             true, "", IDecl->getName(), Result);
+                             true, "", IDecl->getIdentifierName(), Result);
   
   // Build _objc_method_list for class's class methods if needed
   RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
-                             false, "", IDecl->getName(), Result);
+                             false, "", IDecl->getIdentifierName(), Result);
     
   // Protocols referenced in class declaration?
   RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols(),
-                               "CLASS", CDecl->getName(), Result);
+                               "CLASS", CDecl->getIdentifierName(), Result);
     
   
   // Declaration of class/meta-class metadata
@@ -3429,7 +3430,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
 
 void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
-  const char *FuncName = FD->getName();
+  const char *FuncName = FD->getIdentifierName();
   
   SynthesizeBlockLiterals(FunLocStart, FuncName);
 }
@@ -3489,13 +3490,13 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
   const BlockPointerType *CPT = 0;
   
   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
-    closureName = DRE->getDecl()->getName();
+    closureName = DRE->getDecl()->getIdentifierName();
     CPT = DRE->getType()->getAsBlockPointerType();
   } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
-    closureName = CDRE->getDecl()->getName();
+    closureName = CDRE->getDecl()->getIdentifierName();
     CPT = CDRE->getType()->getAsBlockPointerType();
   } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
-    closureName = MExpr->getMemberDecl()->getName();
+    closureName = MExpr->getMemberDecl()->getIdentifierName();
     CPT = MExpr->getType()->getAsBlockPointerType();
   } else {
     assert(1 && "RewriteBlockClass: Bad type");
@@ -3812,15 +3813,15 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
          E = BlockByCopyDecls.end(); I != E; ++I) {
       if (isObjCType((*I)->getType())) {
         // FIXME: Conform to ABI ([[obj retain] autorelease]).
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        FD = SynthBlockInitFunctionDecl((*I)->getIdentifierName());
         Exp = new DeclRefExpr(FD, FD->getType(), SourceLocation());
       } else if (isBlockPointerType((*I)->getType())) {
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        FD = SynthBlockInitFunctionDecl((*I)->getIdentifierName());
         Arg = new DeclRefExpr(FD, FD->getType(), SourceLocation());
         Exp = new CStyleCastExpr(Context->VoidPtrTy, Arg, 
                                  Context->VoidPtrTy, SourceLocation(), SourceLocation());
       } else {
-        FD = SynthBlockInitFunctionDecl((*I)->getName());
+        FD = SynthBlockInitFunctionDecl((*I)->getIdentifierName());
         Exp = new DeclRefExpr(FD, FD->getType(), SourceLocation());
       }
       InitExprs.push_back(Exp); 
@@ -3828,7 +3829,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
     // Output all "by ref" declarations.
     for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 
          E = BlockByRefDecls.end(); I != E; ++I) {
-      FD = SynthBlockInitFunctionDecl((*I)->getName());
+      FD = SynthBlockInitFunctionDecl((*I)->getIdentifierName());
       Exp = new DeclRefExpr(FD, FD->getType(), SourceLocation());
       Exp = new UnaryOperator(Exp, UnaryOperator::AddrOf,
                               Context->getPointerType(Exp->getType()), 
@@ -4064,7 +4065,8 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
     if (VD->getInit()) {
       GlobalVarDecl = VD;
       RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
-      SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
+      SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), 
+                              VD->getIdentifierName());
       GlobalVarDecl = 0;
 
       // This is needed for blocks.
diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html
index 1e1fc990adc..adfa7c3e748 100644
--- a/docs/InternalsManual.html
+++ b/docs/InternalsManual.html
@@ -37,6 +37,7 @@
   <ul>
   <li><a href="#Type">The Type class and its subclasses</a></li>
   <li><a href="#QualType">The QualType class</a></li>
+  <li><a href="#DeclarationName">Declaration names</a></li>
   <li><a href="#CFG">The CFG class</a></li>
   <li><a href="#Constants">Constant Folding in the Clang AST</a></li>
   </ul>
@@ -442,6 +443,107 @@ the low bit of the pointer to the Type object.  This means that QualType is
 exactly the same size as a pointer, and this works fine on any system where
 malloc'd objects are at least 8 byte aligned.</p>
 
+<!-- ======================================================================= -->
+<h3 id="DeclarationName">Declaration names</h3>
+<!-- ======================================================================= -->
+
+<p>The <tt>DeclarationName</tt> class represents the name of a
+  declaration in Clang. Declarations in the C family of languages can
+  take several different forms. Most declarations are named by are
+  simple identifiers, e.g., "<code>f</code>" and "<code>x</code>" in
+  the function declaration <code>f(int x)</code>. In C++, declaration
+  names can also name class constructors ("<code>Class</code>"
+  in <code>struct Class { Class(); }</code>), class destructors
+  ("<code>~Class</code>"), overloaded operator names ("operator+"),
+  and conversion functions ("<code>operator void const *</code>"). In
+  Objective-C, declaration names can refer to the names of Objective-C
+  methods, which involve the method name and the parameters,
+  collectively called a <i>selector</i>, e.g..,
+  "<code>setWidth:height:</code>". Since all of these kinds of
+  entities--variables, functions, Objective-C methods, C++
+  constructors, destructors, and operators---are represented as
+  subclasses of Clang's common <code>NamedDecl</code>
+  class, <code>DeclarationName</code> is designed to efficiently
+  represent any kind of name.</p>
+
+<p>Given
+  a <code>DeclarationName</code> <code>N</code>, <code>N.getNameKind()</code>
+  will produce a valid that describes what kind of name <code>N</code>
+  stores. There are 7 options (all of the names are inside
+  the <code>DeclarationName</code> class)</p>
+<dl>
+  <dt>Identifier</dt>
+  <dd>The name is a simple
+  identifier. Use <code>N.getAsIdentifierInfo()</code> to retrieve the
+  corresponding <code>IdentifierInfo*</code> pointing to the actual
+  identifier. Note that C++ overloaded operators (e.g.,
+  "<code>operator+</code>") are represented as special kinds of
+  identifiers. Use <code>IdentifierInfo</code>'s <code>getOverloadedOperatorID</code>
+  function to determine whether an identifier is an overloaded
+  operator name.</dd>
+
+  <dt>ObjCZeroArgSelector, ObjCOneArgSelector,
+  ObjCMultiArgSelector</dt>
+  <dd>The name is an Objective-C selector, which can be retrieved as a
+    <code>Selector</code> instance
+    via <code>N.getObjCSelector()</code>. The three possible name
+    kinds for Objective-C reflect an optimization within
+    the <code>DeclarationName</code> class: both zero- and
+    one-argument selectors are stored as a
+    masked <code>IdentifierInfo</code> pointer, and therefore require
+    very little space, since zero- and one-argument selectors are far
+    more common than multi-argument selectors (which use a different
+    structure).</dd>
+
+  <dt>CXXConstructorName</dt>
+  <dd>The name is a C++ constructor
+    name. Use <code>N.getCXXNameType()</code> to retrieve
+    the <a href="#QualType">type</a> that this constructor is meant to
+    construct. The type is always the canonical type, since all
+    constructors for a given type have the same name.</dd>
+
+  <dt>CXXDestructorName</dt>
+  <dd>The name is a C++ destructor
+    name. Use <code>N.getCXXNameType()</code> to retrieve
+    the <a href="#QualType">type</a> whose destructor is being
+    named. This type is always a canonical type.</dd>
+
+  <dt>CXXConversionFunctionName</dt>
+  <dd>The name is a C++ conversion function. Conversion functions are
+  named according to the type they convert to, e.g., "<code>operator void
+      const *</code>". Use <code>N.getCXXNameType()</code> to retrieve
+  the type that this conversion function converts to. This type is
+    always a canonical type.</dd>
+</dl>
+
+<p><code>DeclarationName</code>s are cheap to create, copy, and
+  compare. They require only a single pointer's worth of storage in
+  the common cases (identifiers, C++ overloaded operator names, zero-
+  and one-argument Objective-C selectors) and use dense, uniqued
+  storage for the other kinds of
+  names. Two <code>DeclarationName</code>s can be compared for
+  equality (<code>==</code>, <code>!=</code>) using a simple bitwise
+  comparison, can be ordered
+  with <code>&lt;</code>, <code>&gt;</code>, <code>&lt;=</code>,
+  and <code>&gt;=</code> (which provide a lexicographical ordering for
+  normal identifiers but an unspecified ordering for other kinds of
+  names), and can be placed into LLVM <code>DenseMap</code>s
+  and <code>DenseSet</code>s.</p>
+
+<p><code>DeclarationName</code> instances can be created in different
+  ways depending on what kind of name the instance will store. Normal
+  identifiers (<code>IdentifierInfo</code> pointers), including
+  overloaded operator names, and Objective-C selectors
+  (<code>Selector</code>) can be implicitly converted
+  to <code>DeclarationName</code>s. Names for C++ constructors,
+  destructors, and conversion functions can be retrieved from
+  the <code>DeclarationNameTable</code>, an instance of which is
+  available as <code>ASTContext::DeclarationNames</code>. The member
+  functions <code>getCXXConstructorName</code>, <code>getCXXDestructorName</code>,
+  and <code>getCXXConversionFunctionName</code>, respectively,
+  return <code>DeclarationName</code> instances for the three kinds of
+  C++ special function names.</p>
+
 <!-- ======================================================================= -->
 <h3 id="CFG">The <tt>CFG</tt> class</h3>
 <!-- ======================================================================= -->
@@ -736,4 +838,4 @@ interacts with constant evaluation:</p>
 
 </div>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index b5adffdcb0b..46a4e6f5327 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -14,8 +14,10 @@
 #ifndef LLVM_CLANG_AST_ASTCONTEXT_H
 #define LLVM_CLANG_AST_ASTCONTEXT_H
 
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/AST/Builtins.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
@@ -110,7 +112,8 @@ public:
   TargetInfo &Target;
   IdentifierTable &Idents;
   SelectorTable &Selectors;
-  
+  DeclarationNameTable DeclarationNames;
+
   SourceManager& getSourceManager() { return SourceMgr; }
   llvm::MallocAllocator &getAllocator() { return Allocator; }  
   const LangOptions& getLangOptions() const { return LangOpts; }
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 3a766bfd5ec..2ac94a9bdfa 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -14,7 +14,9 @@
 #ifndef LLVM_CLANG_AST_DECL_H
 #define LLVM_CLANG_AST_DECL_H
 
+#include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/OperatorKinds.h"
+#include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/Parse/AccessSpecifier.h"
 #include "llvm/ADT/SmallVector.h"
@@ -24,7 +26,6 @@ class Expr;
 class Stmt;
 class CompoundStmt;
 class StringLiteral;
-class IdentifierInfo;
 
 /// TranslationUnitDecl - The top declaration context.
 /// FIXME: The TranslationUnit class should probably be modified to serve as
@@ -56,19 +57,51 @@ protected:
   friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
 };
 
-/// NamedDecl - This represents a decl with an identifier for a name.  Many
+/// NamedDecl - This represents a decl with a name.  Many
 /// decls have names, but not ObjCMethodDecl, @class, etc.
 class NamedDecl : public Decl {
-  /// Identifier - The identifier for this declaration (e.g. the name for the
-  /// variable, the tag for a struct).
-  IdentifierInfo *Identifier;
+  /// Name - The name of this declaration, which is typically a normal
+  /// identifier but may also be a special kind of name (C++
+  /// constructor, Objective-C selector, etc.)
+  DeclarationName Name;
+
+protected:
+  NamedDecl(Kind DK, SourceLocation L, DeclarationName N)
+    : Decl(DK, L), Name(N) {}
+  
 public:
   NamedDecl(Kind DK, SourceLocation L, IdentifierInfo *Id)
-   : Decl(DK, L), Identifier(Id) {}
+    : Decl(DK, L), Name(Id) {}
+
+  /// getIdentifier - Get the identifier that names this declaration,
+  /// if there is one. This will return NULL if this declaration has
+  /// no name (e.g., for an unnamed class) or if the name is a special
+  /// name (C++ constructor, Objective-C selector, etc.).
+  IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
+
+  /// getIdentifierName - Get the name of identifier for this
+  /// declaration as a string. If the declaration has no name, or if
+  /// the name is a special name (C++ constructor, Objective-C
+  /// selector, etc.), returns NULL.
+  const char *getIdentifierName() const {
+    if (IdentifierInfo *II = getIdentifier())
+      return II->getName();
+    else
+      return 0;
+  }
+
+  /// getDeclName - Get the actual, stored name of the declaration,
+  /// which may be a special name.
+  DeclarationName getDeclName() const { return Name; }
+
+  /// getName - Get a human-readable name for the declaration, even if
+  /// it is one of the special kinds of names (C++ constructor,
+  /// Objective-C selector, etc.). Creating this name requires some
+  /// expensive string manipulation, so it should be called only when
+  /// absolutely critical. For simple declarations, @c
+  /// getIdentifierName() should suffice.
+  std::string getName() const;
   
-  IdentifierInfo *getIdentifier() const { return Identifier; }
-  virtual const char *getName() const;
-    
   static bool classof(const Decl *D) {
     return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
   }
@@ -120,8 +153,8 @@ class ScopedDecl : public NamedDecl {
 
 protected:
   ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
-             IdentifierInfo *Id, ScopedDecl *PrevDecl)
-    : NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0),
+             DeclarationName N, ScopedDecl *PrevDecl)
+    : NamedDecl(DK, L, N), NextDeclarator(PrevDecl), Next(0),
       DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
 
   virtual ~ScopedDecl();
@@ -272,8 +305,8 @@ class ValueDecl : public ScopedDecl {
 
 protected:
   ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
-            IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl) 
-    : ScopedDecl(DK, DC, L, Id, PrevDecl), DeclType(T) {}
+            DeclarationName N, QualType T, ScopedDecl *PrevDecl) 
+    : ScopedDecl(DK, DC, L, N, PrevDecl), DeclType(T) {}
 public:
   QualType getType() const { return DeclType; }
   void setType(QualType newType) { DeclType = newType; }
@@ -512,10 +545,10 @@ private:
   SourceLocation TypeSpecStartLoc;
 protected:
   FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
-               IdentifierInfo *Id, QualType T,
+               DeclarationName N, QualType T,
                StorageClass S, bool isInline, ScopedDecl *PrevDecl,
                SourceLocation TSSL = SourceLocation())
-    : ValueDecl(DK, DC, L, Id, T, PrevDecl), 
+    : ValueDecl(DK, DC, L, N, T, PrevDecl), 
       DeclContext(DK),
       ParamInfo(0), Body(0), PreviousDeclaration(0),
       SClass(S), IsInline(isInline), IsImplicit(0), TypeSpecStartLoc(TSSL) {}
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index f0ac1a5335e..753d572fb3a 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -52,6 +52,7 @@ public:
            ObjCCategory,
            ObjCCategoryImpl,
            ObjCImplementation,
+           ObjCMethod,  // [DeclContext]
            ObjCProtocol,
            ObjCProperty,
     //     ScopedDecl
@@ -75,7 +76,6 @@ public:
                  ParmVar,
            ObjCInterface,  // [DeclContext]
            ObjCCompatibleAlias,
-           ObjCMethod,  // [DeclContext]
            ObjCClass,
            ObjCForwardProtocol,
            ObjCPropertyImpl,
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 39c22aaf70d..8edfc650a4a 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -34,8 +34,8 @@ class CXXConversionDecl;
 /// overloaded functions for name lookup.
 class OverloadedFunctionDecl : public NamedDecl {
 protected:
-  OverloadedFunctionDecl(DeclContext *DC, IdentifierInfo *Id)
-    : NamedDecl(OverloadedFunction, SourceLocation(), Id) { }
+  OverloadedFunctionDecl(DeclContext *DC, DeclarationName N)
+    : NamedDecl(OverloadedFunction, SourceLocation(), N) { }
 
   /// Functions - the set of overloaded functions contained in this
   /// overload set.
@@ -47,16 +47,16 @@ public:
     function_const_iterator;
 
   static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
-                                        IdentifierInfo *Id);
+                                        DeclarationName N);
 
   /// addOverload - Add an overloaded function FD to this set of
   /// overloaded functions.
   void addOverload(FunctionDecl *FD) {
     assert((!getNumFunctions() || (FD->getDeclContext() == getDeclContext())) &&
            "Overloaded functions must all be in the same context");
-    assert((FD->getIdentifier() == getIdentifier() ||
-            isa<CXXConversionDecl>(FD)) &&
-           "Overloaded functions must have the same name or be conversions.");
+    assert((FD->getDeclName() == getDeclName() ||
+            isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
+           "Overloaded functions must have the same name");
     Functions.push_back(FD);
   }
 
@@ -246,7 +246,7 @@ class CXXRecordDecl : public RecordDecl, public DeclContext {
   /// CXXConversionDecl.
   OverloadedFunctionDecl Conversions;
 
-  CXXRecordDecl(ASTContext &C, TagKind TK, DeclContext *DC,
+  CXXRecordDecl(TagKind TK, DeclContext *DC,
                 SourceLocation L, IdentifierInfo *Id);
 
   ~CXXRecordDecl();
@@ -389,9 +389,9 @@ protected:
 class CXXMethodDecl : public FunctionDecl {
 protected:
   CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
-                IdentifierInfo *Id, QualType T,
+                DeclarationName N, QualType T,
                 bool isStatic, bool isInline, ScopedDecl *PrevDecl)
-    : FunctionDecl(DK, RD, L, Id, T, (isStatic ? Static : None),
+    : FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None),
                    isInline, PrevDecl) {}
 
 public:
@@ -576,21 +576,19 @@ class CXXConstructorDecl : public CXXMethodDecl {
   /// FIXME: Add support for base and member initializers.
 
   CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
-                     IdentifierInfo *Id, QualType T,
+                     DeclarationName N, QualType T,
                      bool isExplicit, bool isInline, bool isImplicitlyDeclared)
-    : CXXMethodDecl(CXXConstructor, RD, L, Id, T, false, isInline, /*PrevDecl=*/0),
+    : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline, 
+                    /*PrevDecl=*/0),
       Explicit(isExplicit), ImplicitlyDeclared(isImplicitlyDeclared),
       ImplicitlyDefined(false) { }
 
 public:
   static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
-                                    SourceLocation L, IdentifierInfo *Id,
+                                    SourceLocation L, DeclarationName N,
                                     QualType T, bool isExplicit,
                                     bool isInline, bool isImplicitlyDeclared);
 
-  /// getName - Returns a human-readable name for this constructor.
-  virtual const char *getName() const;
-
   /// isExplicit - Whether this constructor was marked "explicit" or not.  
   bool isExplicit() const { return Explicit; }
 
@@ -686,29 +684,20 @@ class CXXDestructorDecl : public CXXMethodDecl {
   /// @c !ImplicitlyDeclared && ImplicitlyDefined.
   bool ImplicitlyDefined : 1;
 
-  /// Name - The formatted name of this destructor. This will be
-  /// generated when getName() is called.
-  mutable char *Name;
-
   CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
-                    IdentifierInfo *Id, QualType T,
+                    DeclarationName N, QualType T,
                     bool isInline, bool isImplicitlyDeclared)
-    : CXXMethodDecl(CXXDestructor, RD, L, Id, T, false, isInline, 
+    : CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline, 
                     /*PrevDecl=*/0),
       ImplicitlyDeclared(isImplicitlyDeclared),
-      ImplicitlyDefined(false), Name(0) { }
+      ImplicitlyDefined(false) { }
 
 public:
   static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
-                                   SourceLocation L, IdentifierInfo *Id,
+                                   SourceLocation L, DeclarationName N,
                                    QualType T, bool isInline, 
                                    bool isImplicitlyDeclared);
 
-  virtual ~CXXDestructorDecl();
-
-  /// getName - Returns a human-readable name for this destructor.
-  virtual const char *getName() const;
-
   /// isImplicitlyDeclared - Whether this destructor was implicitly
   /// declared. If false, then this destructor was explicitly
   /// declared by the user.
@@ -762,29 +751,19 @@ class CXXConversionDecl : public CXXMethodDecl {
   /// explicitly wrote a cast. This is a C++0x feature.
   bool Explicit : 1;
 
-  /// Name - The formatted name of this conversion function. This will
-  /// be generated when getName() is called.
-  mutable char *Name;
-
   CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
-                    IdentifierInfo *Id, QualType T, 
+                    DeclarationName N, QualType T, 
                     bool isInline, bool isExplicit)
-    : CXXMethodDecl(CXXConversion, RD, L, Id, T, false, isInline, 
+    : CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline, 
                     /*PrevDecl=*/0),
-      Explicit(isExplicit), Name(0) { }
+      Explicit(isExplicit) { }
 
 public:
   static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
-                                   SourceLocation L, IdentifierInfo *Id,
+                                   SourceLocation L, DeclarationName N,
                                    QualType T, bool isInline, 
                                    bool isExplicit);
 
-  virtual ~CXXConversionDecl();
-
-  /// getName - Returns a human-readable name for this conversion
-  /// function.
-  virtual const char *getName() const;
-
   /// isExplicit - Whether this is an explicit conversion operator
   /// (C++0x only). Explicit conversion operators are only considered
   /// when the user has explicitly written a cast.
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index e8c383d73e4..ffbb1e56fb8 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -91,7 +91,7 @@ public:
 /// A selector represents a unique name for a method. The selector names for
 /// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
 ///
-class ObjCMethodDecl : public Decl, public DeclContext {
+class ObjCMethodDecl : public NamedDecl, public DeclContext {
 public:
   enum ImplementationControl { None, Required, Optional };
 private:
@@ -115,9 +115,6 @@ private:
   // Context this method is declared in.
   NamedDecl *MethodContext;
   
-  // A unigue name for this method.
-  Selector SelName;
-  
   // Type of this method.
   QualType MethodDeclType;
   /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
@@ -146,13 +143,13 @@ private:
                  bool isVariadic = false,
                  bool isSynthesized = false,
                  ImplementationControl impControl = None)
-  : Decl(ObjCMethod, beginLoc),
+  : NamedDecl(ObjCMethod, beginLoc, SelInfo),
     DeclContext(ObjCMethod),
     IsInstance(isInstance), IsVariadic(isVariadic),
     IsSynthesized(isSynthesized),
     DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
     MethodContext(static_cast<NamedDecl*>(contextDecl)),
-    SelName(SelInfo), MethodDeclType(T), 
+    MethodDeclType(T), 
     ParamInfo(0), NumMethodParams(0), 
     EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
 
@@ -191,7 +188,7 @@ public:
     return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
   }
   
-  Selector getSelector() const { return SelName; }
+  Selector getSelector() const { return getDeclName().getObjCSelector(); }
   unsigned getSynthesizedMethodSize() const;
   QualType getResultType() const { return MethodDeclType; }
   
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
new file mode 100644
index 00000000000..385e2f34a34
--- /dev/null
+++ b/include/clang/AST/DeclarationName.h
@@ -0,0 +1,294 @@
+//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DeclarationName and DeclarationNameTable classes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
+#define LLVM_CLANG_AST_DECLARATIONNAME_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/Type.h"
+#include "llvm/Bitcode/SerializationFwd.h"
+
+namespace llvm {
+  template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+  class CXXSpecialName;       // a private class used by DeclarationName
+  class DeclarationNameExtra; // a private class used by DeclarationName
+  class IdentifierInfo;
+  class MultiKeywordSelector; // a private class used by Selector and DeclarationName
+
+/// 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 {
+public:
+  /// NameKind - The kind of name this object contains.
+  enum NameKind {
+    Identifier,
+    ObjCZeroArgSelector,
+    ObjCOneArgSelector,
+    ObjCMultiArgSelector,
+    CXXConstructorName,
+    CXXDestructorName,
+    CXXConversionFunctionName
+  };
+
+private:
+  /// StoredNameKind - The kind of name that is actually stored in the
+  /// upper bits of the Ptr field. This is only used internally.
+  enum StoredNameKind {
+    StoredIdentifier = 0,
+    StoredObjCZeroArgSelector,
+    StoredObjCOneArgSelector,
+    StoredObjCMultiArgSelectorOrCXXName,
+    PtrMask = 0x03
+  };
+
+  /// Ptr - The lowest two bits are used to express what kind of name
+  /// we're actually storing, using the values of NameKind. Depending
+  /// on the kind of name this is, the upper bits of Ptr may have one
+  /// of several different meanings:
+  ///
+  ///   Identifier - The name is a normal identifier, and Ptr is a
+  ///   normal IdentifierInfo pointer.  
+  ///
+  ///   ObjCZeroArgSelector - The name is an Objective-C selector with
+  ///   zero arguments, and Ptr is an IdentifierInfo pointer pointing
+  ///   to the selector name.
+  ///
+  ///   ObjCOneArgSelector - The name is an Objective-C selector with
+  ///   one argument, and Ptr is an IdentifierInfo pointer pointing to
+  ///   the selector name.
+  ///
+  ///   ObjCMultiArgSelectorOrCXXName - This is either an Objective-C
+  ///   selector with two or more arguments or it is a C++ name. Ptr
+  ///   is actually a DeclarationNameExtra structure, whose first
+  ///   value will tell us whether this is an Objective-C selector or
+  ///   special C++ name.
+  uintptr_t 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() == StoredObjCMultiArgSelectorOrCXXName &&
+           "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 {
+    if (getNameKind() >= CXXConstructorName && 
+        getNameKind() <= CXXConversionFunctionName)
+      return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
+    else
+      return 0;
+  }
+
+  // Construct a declaration name from the name of a C++ constructor,
+  // destructor, or conversion function.
+  DeclarationName(CXXSpecialName *Name) 
+    : Ptr(reinterpret_cast<uintptr_t>(Name)) { 
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
+    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+  }
+
+  // Construct a declaration name from a zero- or one-argument
+  // Objective-C selector.
+  DeclarationName(IdentifierInfo *II, unsigned numArgs) 
+    : Ptr(reinterpret_cast<uintptr_t>(II)) {
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+    assert(numArgs < 2 && "Use MultiKeywordSelector for >= 2 arguments");
+    if (numArgs == 0)
+      Ptr |= StoredObjCZeroArgSelector;
+    else
+      Ptr |= StoredObjCOneArgSelector;
+  }
+
+  // Construct a declaration name from an Objective-C multiple-keyword
+  // selector.
+  DeclarationName(MultiKeywordSelector *SI)
+    : Ptr(reinterpret_cast<uintptr_t>(SI)) {
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
+    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+  }
+
+  /// Construct a declaration name from a raw pointer.
+  DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
+
+  friend class DeclarationNameTable;
+
+public:
+  /// DeclarationName - Used to create an empty selector.
+  DeclarationName() : Ptr(0) { }
+
+  // Construct a declaration name from an IdentifierInfo *.
+  DeclarationName(IdentifierInfo *II) : Ptr(reinterpret_cast<uintptr_t>(II)) { 
+    assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+  }
+
+  // Construct a declaration name from an Objective-C selector.
+  DeclarationName(Selector Sel);
+
+  /// getNameKind - Determine what kind of name this is.
+  NameKind getNameKind() const;
+
+  /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
+  /// this declaration name, or NULL if this declaration name isn't a
+  /// simple identifier.
+  IdentifierInfo *getAsIdentifierInfo() const { 
+    if (getNameKind() == Identifier)
+      return reinterpret_cast<IdentifierInfo *>(Ptr);
+    else
+      return 0;
+  }
+
+  /// getAsOpaqueInteger - Get the representation of this declaration
+  /// name as an opaque integer.
+  uintptr_t getAsOpaqueInteger() const { return Ptr; }
+
+  /// 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;
+
+  /// getObjCSelector - Get the Objective-C selector stored in this
+  /// declaration name.
+  Selector getObjCSelector() const;
+
+  /// operator== - 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.
+  friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
+    return LHS.Ptr != RHS.Ptr;
+  }
+
+  static DeclarationName getEmptyMarker() {
+    return DeclarationName(uintptr_t(-1));
+  }
+
+  static DeclarationName getTombstoneMarker() {
+    return DeclarationName(uintptr_t(-2));
+  }
+};
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+bool operator<(DeclarationName LHS, DeclarationName RHS);
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
+  return RHS < LHS;
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
+  return !(RHS < LHS);
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
+  return !(LHS < RHS);
+}
+
+/// DeclarationNameTable - 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 {
+  void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
+
+  DeclarationNameTable(const DeclarationNameTable&);            // NONCOPYABLE
+  DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
+
+public:
+  DeclarationNameTable();
+  ~DeclarationNameTable();
+
+  /// getIdentifier - Create a declaration name that is a simple
+  /// identifier.
+  DeclarationName getIdentifier(IdentifierInfo *ID) {
+    return DeclarationName(ID);
+  }
+
+  /// getCXXConstructorName - Returns the name of a C++ constructor
+  /// for the given Type.
+  DeclarationName getCXXConstructorName(QualType Ty) {
+    return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
+  }
+
+  /// getCXXDestructorName - Returns the name of a C++ destructor
+  /// for the given Type.
+  DeclarationName getCXXDestructorName(QualType Ty) {
+    return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
+  }
+
+  /// getCXXConversionFunctionName - Returns the name of a C++
+  /// conversion function for the given Type.
+  DeclarationName getCXXConversionFunctionName(QualType Ty) {
+    return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
+  }
+
+  /// getCXXSpecialName - Returns a declaration name for special kind
+  /// of C++ name, e.g., for a constructor, destructor, or conversion
+  /// function.
+  DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind, 
+                                    QualType Ty);
+};  
+
+}  // end namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that DeclarationNames can be used as keys
+/// in DenseMap and DenseSets.
+template<>
+struct DenseMapInfo<clang::DeclarationName> {
+  static inline clang::DeclarationName getEmptyKey() {
+    return clang::DeclarationName::getEmptyMarker();
+  }
+
+  static inline clang::DeclarationName getTombstoneKey() {
+    return clang::DeclarationName::getTombstoneMarker();
+  }
+
+  static unsigned getHashValue(clang::DeclarationName);
+
+  static inline bool 
+  isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
+    return LHS == RHS;
+  }
+
+  static inline bool isPod() { return true; }
+};
+
+}  // end namespace llvm
+
+#endif
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index f6b95ba380c..a13d4ba538c 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -29,10 +29,11 @@ namespace llvm {
 
 namespace clang {
   struct LangOptions;
-  class MultiKeywordSelector; // a private class used by Selector.
   class IdentifierInfo;
   class SourceLocation;
-  
+  class MultiKeywordSelector; // private class used by Selector
+  class DeclarationName;      // AST class that stores declaration names
+
   /// IdentifierLocPair - A simple pair of identifier info and location.
   typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
   
@@ -281,8 +282,9 @@ class Selector {
   }
   Selector(uintptr_t V) : InfoPtr(V) {}
 public:
-  friend class SelectorTable; // only the SelectorTable can create these.
-  
+  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() : InfoPtr(0) {}
@@ -362,12 +364,35 @@ public:
   static SelectorTable* CreateAndRegister(llvm::Deserializer& D);
 };
 
-}  // end namespace clang
+/// DeclarationNameExtra - Common base of the MultiKeywordSelector and
+/// CXXSpecialName classes, both of which are private classes that can
+/// be stored by the AST's DeclarationName class.
+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.
+  enum ExtraKind {
+    CXXConstructor = 0,
+    CXXDestructor,
+    CXXConversionFunction,
+    NUM_EXTRA_KINDS
+  };
 
+  /// ExtraKindOrNumArgs - Either the kind of C++ special name (if the
+  /// value is one of the CXX* enumerators of ExtraKind), in which
+  /// case the DeclarationNameExtra is also a CXXSpecialName, or
+  /// 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.
+  unsigned ExtraKindOrNumArgs;
+};
+
+}  // end namespace clang
 
+namespace llvm {
 /// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
 /// DenseSets.
-namespace llvm {
 template <>
 struct DenseMapInfo<clang::Selector> {
   static inline clang::Selector getEmptyKey() {
@@ -385,6 +410,6 @@ struct DenseMapInfo<clang::Selector> {
   
   static bool isPod() { return true; }
 };
-}  // end namespace llvm
 
+}  // end namespace llvm
 #endif
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 47ada4fe1a2..e8bd3ac6d6c 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -87,7 +87,7 @@ class Preprocessor {
   /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
   /// the lifetime fo the preprocessor.
   SelectorTable Selectors;
-  
+
   /// PragmaHandlers - This tracks all of the pragmas that the client registered
   /// with this preprocessor.
   PragmaNamespace *PragmaHandlers;
@@ -175,7 +175,7 @@ public:
 
   IdentifierTable &getIdentifierTable() { return Identifiers; }
   SelectorTable &getSelectorTable() { return Selectors; }
-  
+
   inline FullSourceLoc getFullLoc(SourceLocation Loc) const {
     return FullSourceLoc(Loc, getSourceManager());
   }
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e84cc4b3078..ee57816da3f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -33,7 +33,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
                        unsigned size_reserve) : 
   CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0),
   SourceMgr(SM), LangOpts(LOpts), Target(t), 
-  Idents(idents), Selectors(sels) 
+  Idents(idents), Selectors(sels)
 {  
   if (size_reserve > 0) Types.reserve(size_reserve);    
   InitBuiltinTypes();
@@ -996,7 +996,7 @@ QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) {
 /// alphabetically.
 static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
                             const ObjCProtocolDecl *RHS) {
-  return strcmp(LHS->getName(), RHS->getName()) < 0;
+  return LHS->getDeclName() < RHS->getDeclName();
 }
 
 static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
@@ -1449,7 +1449,7 @@ QualType ASTContext::getObjCFastEnumerationStateType()
 // typedef <type> BOOL;
 static bool isTypeTypedefedAsBOOL(QualType T) {
   if (const TypedefType *TT = dyn_cast<TypedefType>(T))
-    return !strcmp(TT->getDecl()->getName(), "BOOL");
+    return !strcmp(TT->getDecl()->getIdentifierName(), "BOOL");
         
   return false;
 }
@@ -2260,7 +2260,8 @@ ASTContext* ASTContext::Create(llvm::Deserializer& D) {
 
   unsigned size_reserve = D.ReadInt();
   
-  ASTContext* A = new ASTContext(LOpts, SM, t, idents, sels, size_reserve);
+  ASTContext* A = new ASTContext(LOpts, SM, t, idents, sels,
+                                 size_reserve);
   
   for (unsigned i = 0; i < size_reserve; ++i)
     Type::Create(*A,i,D);
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index a58b3b162fb..4ac6a6e98e4 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangAST
   ASTContext.cpp
   Builtins.cpp
   CFG.cpp
+  DeclarationName.cpp
   DeclBase.cpp
   Decl.cpp
   DeclCXX.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index fa5e9ce36eb..dc4d6027ee8 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -133,9 +133,47 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
 // NamedDecl Implementation
 //===----------------------------------------------------------------------===//
 
-const char *NamedDecl::getName() const {
-  if (const IdentifierInfo *II = getIdentifier())
-    return II->getName();
+std::string NamedDecl::getName() const {
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
+      return II->getName();
+    return "";
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    return Name.getObjCSelector().getName();
+
+  case DeclarationName::CXXConstructorName: {
+    QualType ClassType = Name.getCXXNameType();
+    if (const RecordType *ClassRec = ClassType->getAsRecordType())
+      return ClassRec->getDecl()->getName();
+    return ClassType.getAsString();
+  }
+
+  case DeclarationName::CXXDestructorName: {
+    std::string Result = "~";
+    QualType Type = Name.getCXXNameType();
+    if (const RecordType *Rec = Type->getAsRecordType())
+      Result += Rec->getDecl()->getName();
+    else
+      Result += Type.getAsString();
+    return Result;
+  }
+
+  case DeclarationName::CXXConversionFunctionName: {
+    std::string Result = "operator ";
+    QualType Type = Name.getCXXNameType();
+    if (const RecordType *Rec = Type->getAsRecordType())
+      Result += Rec->getDecl()->getName();
+    else
+      Result += Type.getAsString();
+    return Result;
+  }
+  }
+
+  assert(false && "Unexpected declaration name kind");
   return "";
 }
 
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 1de640743d9..8855e99a26f 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -27,20 +27,20 @@ CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
   return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
 }
 
-CXXRecordDecl::CXXRecordDecl(ASTContext &C, TagKind TK, DeclContext *DC,
+CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
                              SourceLocation L, IdentifierInfo *Id) 
   : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
     UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
     Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
-    Constructors(DC, &C.Idents.getConstructorId()), 
+    Constructors(DC, DeclarationName()),
     Destructor(0), 
-    Conversions(DC, &C.Idents.getConversionFunctionId()) { }
+    Conversions(DC, DeclarationName()) { }
 
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
                                      SourceLocation L, IdentifierInfo *Id,
                                      CXXRecordDecl* PrevDecl) {
   void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
-  CXXRecordDecl* R = new (Mem) CXXRecordDecl(C, TK, DC, L, Id);
+  CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
   C.getTypeDeclType(R, PrevDecl);  
   return R;
 }
@@ -178,11 +178,13 @@ CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
 
 CXXConstructorDecl *
 CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
-                           SourceLocation L, IdentifierInfo *Id,
+                           SourceLocation L, DeclarationName N,
                            QualType T, bool isExplicit,
                            bool isInline, bool isImplicitlyDeclared) {
+  assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
+         "Name must refer to a constructor");
   void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
-  return new (Mem) CXXConstructorDecl(RD, L, Id, T, isExplicit, isInline,
+  return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
                                       isImplicitlyDeclared);
 }
 
@@ -242,54 +244,26 @@ bool CXXConstructorDecl::isConvertingConstructor() const {
          (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
 }
 
-const char *CXXConstructorDecl::getName() const { 
-  return getParent()->getName();
-}
-
 CXXDestructorDecl *
 CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
-                          SourceLocation L, IdentifierInfo *Id,
+                          SourceLocation L, DeclarationName N,
                           QualType T, bool isInline, 
                           bool isImplicitlyDeclared) {
+  assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
+         "Name must refer to a destructor");
   void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
-  return new (Mem) CXXDestructorDecl(RD, L, Id, T, isInline, 
+  return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline, 
                                      isImplicitlyDeclared);
 }
 
-CXXDestructorDecl::~CXXDestructorDecl() {
-  delete [] Name;
-}
-
-const char *CXXDestructorDecl::getName() const {
-  if (!Name) {
-    std::string Builder = "~";
-    Builder += getParent()->getName();
-    Name = new char[Builder.size()+1];
-    strcpy(Name, Builder.c_str());
-  }
-  return Name;
-}
-
-CXXConversionDecl::~CXXConversionDecl() {
-  delete [] Name;
-}
-
-const char *CXXConversionDecl::getName() const {
-  if (!Name) {
-    std::string Builder = "operator ";
-    Builder += getConversionType().getAsString();
-    Name = new char[Builder.size()+1];
-    strcpy(Name, Builder.c_str());    
-  }
-  return Name;
-}
-
 CXXConversionDecl *
 CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
-                          SourceLocation L, IdentifierInfo *Id,
+                          SourceLocation L, DeclarationName N,
                           QualType T, bool isInline, bool isExplicit) {
+  assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+         "Name must refer to a conversion function");
   void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
-  return new (Mem) CXXConversionDecl(RD, L, Id, T, isInline, isExplicit);
+  return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
 }
 
 CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
@@ -301,9 +275,9 @@ CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
 
 OverloadedFunctionDecl *
 OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
-                               IdentifierInfo *Id) {
+                               DeclarationName N) {
   void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
-  return new (Mem) OverloadedFunctionDecl(DC, Id);
+  return new (Mem) OverloadedFunctionDecl(DC, N);
 }
 
 LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 0d006d676d7..558156c4a02 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -758,11 +758,11 @@ unsigned ObjCMethodDecl::getSynthesizedMethodSize() const {
   // syntesized method name is a concatenation of -/+[class-name selector]
   // Get length of this name.
   unsigned length = 3;  // _I_ or _C_
-  length += strlen(getClassInterface()->getName()) +1; // extra for _
+  length += strlen(getClassInterface()->getIdentifierName()) +1; // extra for _
   NamedDecl *MethodContext = getMethodContext();
   if (ObjCCategoryImplDecl *CID = 
       dyn_cast<ObjCCategoryImplDecl>(MethodContext))
-    length += strlen(CID->getName()) +1;
+    length += strlen(CID->getIdentifierName()) +1;
   length += getSelector().getName().size(); // selector name
   return length; 
 }
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 3df942e8f1f..5137b720c5b 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -129,12 +129,58 @@ void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
 
 void NamedDecl::EmitInRec(Serializer& S) const {
   Decl::EmitInRec(S);
-  S.EmitPtr(getIdentifier());               // From NamedDecl.
+  S.EmitInt(Name.getNameKind());
+
+  switch (Name.getNameKind()) {
+  case DeclarationName::Identifier:
+    S.EmitPtr(Name.getAsIdentifierInfo());
+    break;
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Name.getObjCSelector().Emit(S);
+    break;
+
+  case DeclarationName::CXXConstructorName:
+  case DeclarationName::CXXDestructorName:
+  case DeclarationName::CXXConversionFunctionName:
+    Name.getCXXNameType().Emit(S);
+    break;
+  }
 }
 
 void NamedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
   Decl::ReadInRec(D, C);
-  D.ReadPtr(Identifier);                            // From NamedDecl.  
+
+  DeclarationName::NameKind Kind 
+    = static_cast<DeclarationName::NameKind>(D.ReadInt());
+  switch (Kind) {
+  case DeclarationName::Identifier: {
+    IdentifierInfo *Identifier;
+    D.ReadPtr(Identifier);
+    Name = Identifier;
+    break;
+  }
+
+  case DeclarationName::ObjCZeroArgSelector:
+  case DeclarationName::ObjCOneArgSelector:
+  case DeclarationName::ObjCMultiArgSelector:
+    Name = Selector::ReadVal(D);
+    break;
+
+  case DeclarationName::CXXConstructorName:
+    Name = C.DeclarationNames.getCXXConstructorName(QualType::ReadVal(D));
+    break;
+                                                    
+  case DeclarationName::CXXDestructorName:
+    Name = C.DeclarationNames.getCXXDestructorName(QualType::ReadVal(D));
+    break;
+
+  case DeclarationName::CXXConversionFunctionName:
+    Name = C.DeclarationNames.getCXXConversionFunctionName(QualType::ReadVal(D));
+    break;
+  }
 }
 
 //===----------------------------------------------------------------------===//
@@ -434,7 +480,7 @@ FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
   
   void *Mem = C.getAllocator().Allocate<FunctionDecl>();
   FunctionDecl* decl = new (Mem)
-    FunctionDecl(Function, 0, SourceLocation(), NULL,
+    FunctionDecl(Function, 0, SourceLocation(), DeclarationName(),
                  QualType(), SClass, IsInline, 0);
   
   decl->ValueDecl::ReadInRec(D, C);
@@ -495,7 +541,7 @@ OverloadedFunctionDecl *
 OverloadedFunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
   void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
   OverloadedFunctionDecl* decl = new (Mem)
-    OverloadedFunctionDecl(0, NULL);
+    OverloadedFunctionDecl(0, DeclarationName());
   
   decl->NamedDecl::ReadInRec(D, C);
 
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
new file mode 100644
index 00000000000..96e194be8c9
--- /dev/null
+++ b/lib/AST/DeclarationName.cpp
@@ -0,0 +1,166 @@
+//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DeclarationName and DeclarationNameTable
+// classes.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Bitcode/Serialize.h"
+#include "llvm/Bitcode/Deserialize.h"
+using namespace clang;
+
+namespace clang {
+/// 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:
+  QualType Type;
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    ID.AddInteger(ExtraKindOrNumArgs);
+    ID.AddPointer(Type.getAsOpaquePtr());
+  }
+};
+
+bool operator<(DeclarationName LHS, DeclarationName RHS) {
+  if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
+    if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
+      return strcmp(LhsId->getName(), RhsId->getName()) < 0;
+
+  return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
+}
+
+} // end namespace clang
+
+DeclarationName::DeclarationName(Selector Sel) {
+  switch (Sel.getNumArgs()) {
+  case 0:
+    Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
+    Ptr |= StoredObjCZeroArgSelector;
+    break;
+
+  case 1:
+    Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
+    Ptr |= StoredObjCOneArgSelector;
+    break;
+
+  default:
+    Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
+    Ptr |= StoredObjCMultiArgSelectorOrCXXName;
+    break;
+  }
+}
+
+DeclarationName::NameKind DeclarationName::getNameKind() const {
+  switch (getStoredNameKind()) {
+  case StoredIdentifier:          return Identifier;
+  case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
+  case StoredObjCOneArgSelector:  return ObjCOneArgSelector;
+
+  case StoredObjCMultiArgSelectorOrCXXName:
+    switch (getExtra()->ExtraKindOrNumArgs) {
+    case DeclarationNameExtra::CXXConstructor: 
+      return CXXConstructorName;
+
+    case DeclarationNameExtra::CXXDestructor: 
+      return CXXDestructorName;
+
+    case DeclarationNameExtra::CXXConversionFunction: 
+      return CXXConversionFunctionName;
+
+    default:
+      return ObjCMultiArgSelector;
+    }
+    break;
+  }
+
+  // Can't actually get here.
+  return Identifier;
+}
+
+QualType DeclarationName::getCXXNameType() const {
+  if (CXXSpecialName *CXXName = getAsCXXSpecialName())
+    return CXXName->Type;
+  else
+    return QualType();
+}
+
+Selector DeclarationName::getObjCSelector() const {
+  switch (getNameKind()) {
+  case ObjCZeroArgSelector:
+    return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
+
+  case ObjCOneArgSelector:
+    return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
+
+  case ObjCMultiArgSelector:
+    return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
+
+  default:
+    break;
+  }
+
+  return Selector();
+}
+
+DeclarationNameTable::DeclarationNameTable() {
+  CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
+}
+
+DeclarationNameTable::~DeclarationNameTable() {
+  delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
+}
+
+DeclarationName 
+DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, 
+                                        QualType Ty) {
+  assert(Kind >= DeclarationName::CXXConstructorName &&
+         Kind <= DeclarationName::CXXConversionFunctionName &&
+         "Kind must be a C++ special name kind");
+  
+  llvm::FoldingSet<CXXSpecialName> *SpecialNames 
+    = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
+
+  DeclarationNameExtra::ExtraKind EKind;
+  switch (Kind) {
+  case DeclarationName::CXXConstructorName: 
+    EKind = DeclarationNameExtra::CXXConstructor;
+    break;
+  case DeclarationName::CXXDestructorName:
+    EKind = DeclarationNameExtra::CXXDestructor;
+    break;
+  case DeclarationName::CXXConversionFunctionName:
+    EKind = DeclarationNameExtra::CXXConversionFunction;
+    break;
+  default:
+    return DeclarationName();
+  }
+
+  // Unique selector, to guarantee there is one per name.
+  llvm::FoldingSetNodeID ID;
+  ID.AddInteger(EKind);
+  ID.AddPointer(Ty.getAsOpaquePtr());
+
+  void *InsertPos = 0;
+  if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
+    return DeclarationName(Name);
+
+  CXXSpecialName *SpecialName = new CXXSpecialName;
+  SpecialName->ExtraKindOrNumArgs = EKind;
+  SpecialName->Type = Ty;
+
+  SpecialNames->InsertNode(SpecialName, InsertPos);
+  return DeclarationName(SpecialName);
+}
+
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 0b9e62d2c56..a992efba50a 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -202,7 +202,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
   if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
     fprintf(F, "\"typedef %s %s\"",
             localType->getUnderlyingType().getAsString().c_str(),
-            localType->getName());
+            localType->getIdentifierName());
   } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     fprintf(F, "\"");
     // Emit storage class for vardecls.
@@ -295,14 +295,16 @@ void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
     default: fprintf(F,"Decl"); break;
   }
   
-  fprintf(F, "='%s' %p", Node->getDecl()->getName(), (void*)Node->getDecl());
+  fprintf(F, "='%s' %p", Node->getDecl()->getName().c_str(), 
+          (void*)Node->getDecl());
 }
 
 void StmtDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
   DumpExpr(Node);
 
   fprintf(F, " %sDecl='%s' %p", Node->getDecl()->getDeclKindName(), 
-                            Node->getDecl()->getName(), (void*)Node->getDecl());
+                            Node->getDecl()->getIdentifierName(), 
+          (void*)Node->getDecl());
   if (Node->isFreeIvar())
     fprintf(F, " isFreeIvar");
 }
@@ -373,7 +375,8 @@ void StmtDumper::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
 void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
   DumpExpr(Node);
   fprintf(F, " %s%s %p", Node->isArrow() ? "->" : ".",
-          Node->getMemberDecl()->getName(), (void*)Node->getMemberDecl());
+          Node->getMemberDecl()->getName().c_str(), 
+          (void*)Node->getMemberDecl());
 }
 void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
   DumpExpr(Node);
@@ -461,7 +464,7 @@ void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
   DumpExpr(Node);
   
   fprintf(F, " ");
-  fprintf(F, "%s", Node->getProtocol()->getName());
+  fprintf(F, "%s", Node->getProtocol()->getIdentifierName());
 }
 
 void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
@@ -474,7 +477,8 @@ void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
             Getter->getSelector().getName().c_str(),
             Setter ? Setter->getSelector().getName().c_str() : "(null)");
   } else {
-    fprintf(F, " Kind=PropertyRef Property=\"%s\"", Node->getProperty()->getName());
+    fprintf(F, " Kind=PropertyRef Property=\"%s\"", 
+            Node->getProperty()->getIdentifierName());
   }
 }
 
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 4d737c50bc0..b83266d1ff8 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -297,22 +297,22 @@ unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
   return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
 }
 
-
+namespace clang {
 /// MultiKeywordSelector - 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.
-namespace clang {
-class MultiKeywordSelector : public llvm::FoldingSetNode {
+class MultiKeywordSelector 
+  : public DeclarationNameExtra, public llvm::FoldingSetNode {
   friend SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer&);
-  MultiKeywordSelector(unsigned nKeys) : NumArgs(nKeys) {}
+  MultiKeywordSelector(unsigned nKeys) {
+    ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
+  }
 public:  
-  unsigned NumArgs;
-
   // Constructor for keyword selectors.
   MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
     assert((nKeys > 1) && "not a multi-keyword selector");
-    NumArgs = nKeys;
+    ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
     
     // Fill in the trailing keyword array.
     IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
@@ -323,17 +323,17 @@ public:
   // getName - Derive the full selector name and return it.
   std::string getName() const;
     
-  unsigned getNumArgs() const { return NumArgs; }
+  unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
   
   typedef IdentifierInfo *const *keyword_iterator;
   keyword_iterator keyword_begin() const {
     return reinterpret_cast<keyword_iterator>(this+1);
   }
   keyword_iterator keyword_end() const { 
-    return keyword_begin()+NumArgs; 
+    return keyword_begin()+getNumArgs(); 
   }
   IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
-    assert(i < NumArgs && "getIdentifierInfoForSlot(): illegal index");
+    assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
     return keyword_begin()[i];
   }
   static void Profile(llvm::FoldingSetNodeID &ID, 
@@ -343,7 +343,7 @@ public:
       ID.AddPointer(ArgTys[i]);
   }
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, keyword_begin(), NumArgs);
+    Profile(ID, keyword_begin(), getNumArgs());
   }
 };
 } // end namespace clang.
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 9a04a83d6e6..55ce237e14f 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -152,7 +152,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
   
   // We don't set size information, but do specify where the typedef was
   // declared.
-  const char *TyName = Ty->getDecl()->getName();
+  const char *TyName = Ty->getDecl()->getIdentifierName();
   SourceLocation DefLoc = Ty->getDecl()->getLocation();
   llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
 
@@ -206,7 +206,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
   SourceManager &SM = M->getContext().getSourceManager();
 
   // Get overall information about the record type for the debug info.
-  const char *Name = Decl->getName();
+  const char *Name = Decl->getIdentifierName();
   if (Name == 0) Name = "";
 
   llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation());
@@ -242,7 +242,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
     FieldDecl *Field = *I;
     llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
     
-    const char *FieldName = Field->getName();
+    const char *FieldName = Field->getIdentifierName();
     if (FieldName == 0) FieldName = "";
 
     // Get the location for the field.
@@ -301,7 +301,8 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
   llvm::DIArray EltArray =
     DebugFactory.GetOrCreateArray(&Enumerators[0], Enumerators.size());
 
-  const char *EnumName = Decl->getName() ? Decl->getName() : "";
+  const char *EnumName 
+    = Decl->getIdentifierName() ? Decl->getIdentifierName() : "";
   SourceLocation DefLoc = Decl->getLocation();
   llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
   SourceManager &SM = M->getContext().getSourceManager();
@@ -515,7 +516,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
   llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
   SourceManager &SM = M->getContext().getSourceManager();
   uint64_t LineNo = SM.getLogicalLineNumber(Decl->getLocation());
-  const char *Name = Decl->getName();
+  const char *Name = Decl->getIdentifierName();
   
   DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
                                     getOrCreateType(Decl->getType(), Unit),
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index e54c4b386db..7a86d24801f 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -146,7 +146,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
     if (!Target.useGlobalsForAutomaticVariables()) {
       // A normal fixed sized variable becomes an alloca in the entry block.
       const llvm::Type *LTy = ConvertType(Ty);
-      llvm::AllocaInst * Alloc = CreateTempAlloca(LTy, D.getName());
+      llvm::AllocaInst * Alloc = CreateTempAlloca(LTy, D.getIdentifierName());
       unsigned align = getContext().getTypeAlign(Ty);
       if (const AlignedAttr* AA = D.getAttr<AlignedAttr>())
         align = std::max(align, AA->getAlignment());
@@ -164,7 +164,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
     // FIXME: VLA: Add VLA support. For now just make up enough to let
     // the compile go through.
     const llvm::Type *LTy = ConvertType(Ty);
-    llvm::AllocaInst * Alloc = CreateTempAlloca(LTy, D.getName());
+    llvm::AllocaInst * Alloc = CreateTempAlloca(LTy, D.getIdentifierName());
     DeclPtr = Alloc;
   }
   
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 4726be21151..0833b0832d7 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -561,7 +561,7 @@ llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
 
 void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
   ASTContext &Context = CGM.getContext();
-  const char *ProtocolName = PD->getName();
+  const char *ProtocolName = PD->getIdentifierName();
   llvm::SmallVector<std::string, 16> Protocols;
   for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
        E = PD->protocol_end(); PI != E; ++PI)
@@ -616,8 +616,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
 }
 
 void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
-  const char *ClassName = OCD->getClassInterface()->getName();
-  const char *CategoryName = OCD->getName();
+  const char *ClassName = OCD->getClassInterface()->getIdentifierName();
+  const char *CategoryName = OCD->getIdentifierName();
   // Collect information about instance methods
   llvm::SmallVector<Selector, 16> InstanceMethodSels;
   llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
@@ -675,12 +675,12 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
     OID->getClassInterface()->getSuperClass();
   const char * SuperClassName = NULL;
   if (SuperClassDecl) {
-    SuperClassName = SuperClassDecl->getName();
+    SuperClassName = SuperClassDecl->getIdentifierName();
   }
 
   // Get the class name
   ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface();
-  const char * ClassName = ClassDecl->getName();
+  const char * ClassName = ClassDecl->getIdentifierName();
 
   // Get the size of instances.  For runtimes that support late-bound instances
   // this should probably be something different (size just of instance
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 296b1af5518..a8f6bbab9b4 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -638,7 +638,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
   // over.
   LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
 
-  const char *ProtocolName = PD->getName();
+  const char *ProtocolName = PD->getIdentifierName();
 
   // Construct method lists.
   std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
@@ -1050,7 +1050,7 @@ static bool IsClassHidden(const ObjCInterfaceDecl *ID) {
 void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
   DefinedSymbols.insert(ID->getIdentifier());
 
-  const char *ClassName = ID->getName();
+  const char *ClassName = ID->getIdentifierName();
   // FIXME: Gross
   ObjCInterfaceDecl *Interface = 
     const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
@@ -1143,7 +1143,7 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
                                          llvm::Constant *Protocols,
                                          const llvm::Type *InterfaceTy,
                                          const ConstantVector &Methods) {
-  const char *ClassName = ID->getName();
+  const char *ClassName = ID->getIdentifierName();
   unsigned Flags = eClassFlags_Meta;
   unsigned Size = CGM.getTargetData().getABITypeSize(ObjCTypes.ClassTy);
 
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index ff05f6e5855..b358993665d 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -121,7 +121,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
   if (CGDebugInfo *DI = CGM.getDebugInfo()) {
     DI->setLocation(StartLoc);
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-      DI->EmitFunctionStart(FD->getName(), RetTy, CurFn, Builder);
+      DI->EmitFunctionStart(FD->getIdentifierName(), RetTy, CurFn, Builder);
     } else {
       // Just use LLVM function name.
       DI->EmitFunctionStart(Fn->getName().c_str(), 
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1ecaaa370a4..48073694a32 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -877,9 +877,13 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);
 
       // Create the new declaration
+      QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
+      ClassType = Context.getCanonicalType(ClassType);
+      DeclarationName ConName
+        = Context.DeclarationNames.getCXXConstructorName(ClassType);
       NewFD = CXXConstructorDecl::Create(Context, 
                                          cast<CXXRecordDecl>(DC),
-                                         D.getIdentifierLoc(), II, R,
+                                         D.getIdentifierLoc(), ConName, R,
                                          isExplicit, isInline,
                                          /*isImplicitlyDeclared=*/false);
 
@@ -890,9 +894,14 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       if (DC->isCXXRecord()) {
         bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
 
+        QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
+        ClassType = Context.getCanonicalType(ClassType);
+        DeclarationName DesName
+          = Context.DeclarationNames.getCXXDestructorName(ClassType);
+
         NewFD = CXXDestructorDecl::Create(Context,
                                           cast<CXXRecordDecl>(DC),
-                                          D.getIdentifierLoc(), II, R, 
+                                          D.getIdentifierLoc(), DesName, R, 
                                           isInline,
                                           /*isImplicitlyDeclared=*/false);
 
@@ -916,9 +925,14 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       } else {
         bool isInvalidDecl = CheckConversionDeclarator(D, R, SC);
 
+        QualType ConvType = R->getAsFunctionType()->getResultType();
+        ConvType = Context.getCanonicalType(ConvType);
+        DeclarationName ConvName
+          = Context.DeclarationNames.getCXXConversionFunctionName(ConvType);
+
         NewFD = CXXConversionDecl::Create(Context, 
                                           cast<CXXRecordDecl>(DC),
-                                          D.getIdentifierLoc(), II, R,
+                                          D.getIdentifierLoc(), ConvName, R,
                                           isInline, isExplicit);
         
         if (isInvalidDecl)
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f8369b3d8da..2fb1332281e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -725,6 +725,9 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
 /// [special]p1).  This routine can only be executed just before the
 /// definition of the class is complete.
 void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+  QualType ClassType = Context.getTypeDeclType(ClassDecl);
+  ClassType = Context.getCanonicalType(ClassType);
+
   if (!ClassDecl->hasUserDeclaredConstructor()) {
     // C++ [class.ctor]p5:
     //   A default constructor for a class X is a constructor of class X
@@ -732,10 +735,11 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
     //   user-declared constructor for class X, a default constructor is
     //   implicitly declared. An implicitly-declared default constructor
     //   is an inline public member of its class.
+    DeclarationName Name 
+      = Context.DeclarationNames.getCXXConstructorName(ClassType);
     CXXConstructorDecl *DefaultCon = 
       CXXConstructorDecl::Create(Context, ClassDecl,
-                                 ClassDecl->getLocation(),
-                                 &Context.Idents.getConstructorId(),
+                                 ClassDecl->getLocation(), Name,
                                  Context.getFunctionType(Context.VoidTy,
                                                          0, 0, false, 0),
                                  /*isExplicit=*/false,
@@ -798,10 +802,11 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
 
     //  An implicitly-declared copy constructor is an inline public
     //  member of its class.
+    DeclarationName Name 
+      = Context.DeclarationNames.getCXXConstructorName(ClassType);
     CXXConstructorDecl *CopyConstructor
       = CXXConstructorDecl::Create(Context, ClassDecl,
-                                   ClassDecl->getLocation(),
-                                   &Context.Idents.getConstructorId(),
+                                   ClassDecl->getLocation(), Name,
                                    Context.getFunctionType(Context.VoidTy,
                                                            &ArgType, 1,
                                                            false, 0),
@@ -825,10 +830,11 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
     //   If a class has no user-declared destructor, a destructor is
     //   declared implicitly. An implicitly-declared destructor is an
     //   inline public member of its class.
+    DeclarationName Name 
+      = Context.DeclarationNames.getCXXDestructorName(ClassType);
     CXXDestructorDecl *Destructor 
       = CXXDestructorDecl::Create(Context, ClassDecl,
-                                  ClassDecl->getLocation(),
-                                  &Context.Idents.getConstructorId(),
+                                  ClassDecl->getLocation(), Name,
                                   Context.getFunctionType(Context.VoidTy,
                                                           0, 0, false, 0),
                                   /*isInline=*/true,
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 6c17d5f1f6c..8eeb2d367d7 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -302,7 +302,8 @@ Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
          E = IDecl->classprop_end(); I != E; ++I) {
       ObjCPropertyDecl *PDecl = (*I);
       if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
-          DiagnosePropertyMismatch(PDecl, SuperPDecl, SDecl->getName());
+          DiagnosePropertyMismatch(PDecl, SuperPDecl, 
+                                   SDecl->getIdentifierName());
     }
   }
 }
@@ -329,7 +330,7 @@ Sema::MergeOneProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
       mergeProperties.push_back(Pr);
     else
       // Property protocol already exist in class. Diagnose any mismatch.
-      DiagnosePropertyMismatch((*CP), Pr, PDecl->getName());
+      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifierName());
     }
   IDecl->mergeProperties(&mergeProperties[0], mergeProperties.size());
 }
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 58ab5aa7596..f18b98fc13a 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -209,7 +209,7 @@ void UserDefinedConversionSequence::DebugPrint() const {
     Before.DebugPrint();
     fprintf(stderr, " -> ");
   }
-  fprintf(stderr, "'%s'", ConversionFunction->getName());
+  fprintf(stderr, "'%s'", ConversionFunction->getName().c_str());
   if (After.First || After.Second || After.Third) {
     fprintf(stderr, " -> ");
     After.DebugPrint();
-- 
GitLab