Remember declaration scope qualifiers in the AST.  Imposes no memory overhead
on unqualified declarations.

Patch by Enea Zaffanella!  Minimal adjustments:  allocate the ExtInfo nodes
with the ASTContext and delete them during Destroy().  I audited a bunch of
Destroy methods at the same time, to ensure that the correct teardown was
being done.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98540 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 650bb53..3b49959 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1592,6 +1592,12 @@
                                       Name.getAsIdentifierInfo(),
                                       Importer.Import(D->getTagKeywordLoc()),
                                       0);
+  // Import the qualifier, if any.
+  if (D->getQualifier()) {
+    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+    SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+    D2->setQualifierInfo(NNS, NNSRange);
+  }
   D2->setAccess(D->getAccess());
   D2->setLexicalDeclContext(LexicalDC);
   Importer.Imported(D, D2);
@@ -1734,6 +1740,12 @@
                                     Name.getAsIdentifierInfo(), 
                                     Importer.Import(D->getTagKeywordLoc()));
     }
+    // Import the qualifier, if any.
+    if (D->getQualifier()) {
+      NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+      SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+      D2->setQualifierInfo(NNS, NNSRange);
+    }
     D2->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDecl(D2);
   }
@@ -1900,6 +1912,13 @@
                                       D->isInlineSpecified(),
                                       D->hasWrittenPrototype());
   }
+
+  // Import the qualifier, if any.
+  if (D->getQualifier()) {
+    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+    SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+    ToFunction->setQualifierInfo(NNS, NNSRange);
+  }
   ToFunction->setAccess(D->getAccess());
   ToFunction->setLexicalDeclContext(LexicalDC);
   Importer.Imported(D, ToFunction);
@@ -2110,6 +2129,12 @@
   VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc, 
                                    Name.getAsIdentifierInfo(), T, TInfo,
                                    D->getStorageClass());
+  // Import the qualifier, if any.
+  if (D->getQualifier()) {
+    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
+    SourceRange NNSRange = Importer.Import(D->getQualifierRange());
+    ToVar->setQualifierInfo(NNS, NNSRange);
+  }
   ToVar->setAccess(D->getAccess());
   ToVar->setLexicalDeclContext(LexicalDC);
   Importer.Imported(D, ToVar);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 23f5fba..f568d1c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -495,9 +495,16 @@
 // DeclaratorDecl Implementation
 //===----------------------------------------------------------------------===//
 
+DeclaratorDecl::~DeclaratorDecl() {}
+void DeclaratorDecl::Destroy(ASTContext &C) {
+  if (hasExtInfo())
+    C.Deallocate(getExtInfo());
+  ValueDecl::Destroy(C);
+}
+
 SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
   if (DeclInfo) {
-    TypeLoc TL = DeclInfo->getTypeLoc();
+    TypeLoc TL = getTypeSourceInfo()->getTypeLoc();
     while (true) {
       TypeLoc NextTL = TL.getNextTypeLoc();
       if (!NextTL)
@@ -508,6 +515,36 @@
   return SourceLocation();
 }
 
+void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
+                                      SourceRange QualifierRange) {
+  if (Qualifier) {
+    // Make sure the extended decl info is allocated.
+    if (!hasExtInfo()) {
+      // Save (non-extended) type source info pointer.
+      TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
+      // Allocate external info struct.
+      DeclInfo = new (getASTContext()) ExtInfo;
+      // Restore savedTInfo into (extended) decl info.
+      getExtInfo()->TInfo = savedTInfo;
+    }
+    // Set qualifier info.
+    getExtInfo()->NNS = Qualifier;
+    getExtInfo()->NNSRange = QualifierRange;
+  }
+  else {
+    // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
+    assert(QualifierRange.isInvalid());
+    if (hasExtInfo()) {
+      // Save type source info pointer.
+      TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
+      // Deallocate the extended decl info.
+      getASTContext().Deallocate(getExtInfo());
+      // Restore savedTInfo into (non-extended) decl info.
+      DeclInfo = savedTInfo;
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // VarDecl Implementation
 //===----------------------------------------------------------------------===//
@@ -542,7 +579,7 @@
     }
   }
   this->~VarDecl();
-  C.Deallocate((void *)this);
+  DeclaratorDecl::Destroy(C);
 }
 
 VarDecl::~VarDecl() {
@@ -818,7 +855,7 @@
   
   C.Deallocate(ParamInfo);
 
-  Decl::Destroy(C);
+  DeclaratorDecl::Destroy(C);
 }
 
 void FunctionDecl::getNameForDiagnostic(std::string &S,
@@ -1348,6 +1385,12 @@
 // TagDecl Implementation
 //===----------------------------------------------------------------------===//
 
+void TagDecl::Destroy(ASTContext &C) {
+  if (hasExtInfo())
+    C.Deallocate(getExtInfo());
+  TypeDecl::Destroy(C);
+}
+
 SourceRange TagDecl::getSourceRange() const {
   SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
   return SourceRange(TagKeywordLoc, E);
@@ -1409,6 +1452,26 @@
   }
 }
 
+void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
+                               SourceRange QualifierRange) {
+  if (Qualifier) {
+    // Make sure the extended qualifier info is allocated.
+    if (!hasExtInfo())
+      TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
+    // Set qualifier info.
+    getExtInfo()->NNS = Qualifier;
+    getExtInfo()->NNSRange = QualifierRange;
+  }
+  else {
+    // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
+    assert(QualifierRange.isInvalid());
+    if (hasExtInfo()) {
+      getASTContext().Deallocate(getExtInfo());
+      TypedefDeclOrQualifier = (TypedefDecl*) 0;
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // EnumDecl Implementation
 //===----------------------------------------------------------------------===//
@@ -1422,7 +1485,7 @@
 }
 
 void EnumDecl::Destroy(ASTContext& C) {
-  Decl::Destroy(C);
+  TagDecl::Destroy(C);
 }
 
 void EnumDecl::completeDefinition(QualType NewType,
@@ -1529,7 +1592,7 @@
   // together. They are all top-level Decls.
 
   this->~NamespaceDecl();
-  C.Deallocate((void *)this);
+  Decl::Destroy(C);
 }
 
 
@@ -1563,7 +1626,7 @@
 
 void EnumConstantDecl::Destroy(ASTContext& C) {
   if (Init) Init->Destroy(C);
-  Decl::Destroy(C);
+  ValueDecl::Destroy(C);
 }
 
 TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 6deadcc..37f7479 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -943,8 +943,7 @@
 void StaticAssertDecl::Destroy(ASTContext& C) {
   AssertExpr->Destroy(C);
   Message->Destroy(C);
-  this->~StaticAssertDecl();
-  C.Deallocate((void *)this);
+  Decl::Destroy(C);
 }
 
 StaticAssertDecl::~StaticAssertDecl() {