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
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e84cc4b..ee57816 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -33,7 +33,7 @@
                        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 @@
 /// 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 @@
 // 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 @@
 
   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 a58b3b1..4ac6a6e 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -5,6 +5,7 @@
   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 fa5e9ce..dc4d602 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -133,9 +133,47 @@
 // 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 1de6407..8855e99 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -27,20 +27,20 @@
   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 @@
 
 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 @@
          (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 @@
 
 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 0d006d6..558156c 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -758,11 +758,11 @@
   // 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 3df942e..5137b72 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -129,12 +129,58 @@
 
 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 @@
   
   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::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 0000000..96e194b
--- /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 0b9e62d..a992efb 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -202,7 +202,7 @@
   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 @@
     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::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 @@
   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 @@
             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 4d737c5..b83266d 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -297,22 +297,22 @@
   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 @@
   // 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 @@
       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 9a04a83..55ce237 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -152,7 +152,7 @@
   
   // 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 @@
   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 @@
     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::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 @@
   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 e54c4b3..7a86d24 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -146,7 +146,7 @@
     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 @@
     // 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 4726be2..0833b08 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -561,7 +561,7 @@
 
 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::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 @@
     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 296b1af..a8f6bba 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -638,7 +638,7 @@
   // 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 @@
 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 *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 ff05f6e..b358993 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -121,7 +121,7 @@
   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 1ecaaa3..4807369 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -877,9 +877,13 @@
       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 @@
       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 @@
       } 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 f8369b3..2fb1332 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -725,6 +725,9 @@
 /// [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 @@
     //   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 @@
 
     //  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 @@
     //   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 6c17d5f..8eeb2d3 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -302,7 +302,8 @@
          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 @@
       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 58ab5aa..f18b98f 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -209,7 +209,7 @@
     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();