Use NestedNameSpecifierLoc within out-of-line variables, function, and
tag definitions. Also, add support for template instantiation of
NestedNameSpecifierLocs.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126470 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 2d85374..037594a 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -265,7 +265,8 @@
   BufferCapacity = 0;
 }
 
-NestedNameSpecifierLoc CXXScopeSpec::getWithLocInContext(ASTContext &Context) {
+NestedNameSpecifierLoc 
+CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
   if (isEmpty() || isInvalid())
     return NestedNameSpecifierLoc();
   
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 75e7c6f..d6efd7a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2895,8 +2895,7 @@
 static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
   CXXScopeSpec &SS = D.getCXXScopeSpec();
   if (!SS.isSet()) return;
-  DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
-                       SS.getRange());
+  DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
 }
 
 NamedDecl*
@@ -6445,9 +6444,7 @@
   // Maybe add qualifier info.
   if (SS.isNotEmpty()) {
     if (SS.isSet()) {
-      NestedNameSpecifier *NNS
-        = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
-      New->setQualifierInfo(NNS, SS.getRange());
+      New->setQualifierInfo(SS.getWithLocInContext(Context));
       if (NumMatchedTemplateParamLists > 0) {
         New->setTemplateParameterListsInfo(Context,
                                            NumMatchedTemplateParamLists,
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index bef1bb4..893cf6a 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2841,7 +2841,7 @@
                                 FD->getType(), FD->getTypeSourceInfo());
     if (FD->getQualifier()) {
       FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
-      NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange());
+      NewFD->setQualifierInfo(FD->getQualifierLoc());
     }
   } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
     NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
@@ -2851,7 +2851,7 @@
                            VD->getStorageClassAsWritten());
     if (VD->getQualifier()) {
       VarDecl *NewVD = cast<VarDecl>(NewD);
-      NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
+      NewVD->setQualifierInfo(VD->getQualifierLoc());
     }
   }
   return NewD;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 8f7b7da..5b09dfc 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -783,8 +783,7 @@
 
 static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
   if (SS.isSet())
-    T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
-                        SS.getRange());
+    T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
 }
 
 DeclResult
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 44f5913..ae0ac9c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2140,6 +2140,17 @@
   return Instantiator.TransformNestedNameSpecifier(NNS, Range);
 }
 
+NestedNameSpecifierLoc
+Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+                        const MultiLevelTemplateArgumentList &TemplateArgs) {  
+  if (!NNS)
+    return NestedNameSpecifierLoc();
+  
+  TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
+                                    DeclarationName());
+  return Instantiator.TransformNestedNameSpecifierLoc(NNS);
+}
+
 /// \brief Do template substitution on declaration name info.
 DeclarationNameInfo
 Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e1a7065..f437cd3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -27,33 +27,33 @@
 
 bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
                                               DeclaratorDecl *NewDecl) {
-  NestedNameSpecifier *OldQual = OldDecl->getQualifier();
-  if (!OldQual) return false;
-
-  SourceRange QualRange = OldDecl->getQualifierRange();
-
-  NestedNameSpecifier *NewQual
-    = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
-  if (!NewQual)
+  if (!OldDecl->getQualifierLoc())
+    return false;
+  
+  NestedNameSpecifierLoc NewQualifierLoc
+    = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), 
+                                          TemplateArgs);
+  
+  if (!NewQualifierLoc)
     return true;
-
-  NewDecl->setQualifierInfo(NewQual, QualRange);
+  
+  NewDecl->setQualifierInfo(NewQualifierLoc);
   return false;
 }
 
 bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
                                               TagDecl *NewDecl) {
-  NestedNameSpecifier *OldQual = OldDecl->getQualifier();
-  if (!OldQual) return false;
-
-  SourceRange QualRange = OldDecl->getQualifierRange();
-
-  NestedNameSpecifier *NewQual
-    = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
-  if (!NewQual)
+  if (!OldDecl->getQualifierLoc())
+    return false;
+  
+  NestedNameSpecifierLoc NewQualifierLoc
+  = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), 
+                                        TemplateArgs);
+  
+  if (!NewQualifierLoc)
     return true;
-
-  NewDecl->setQualifierInfo(NewQual, QualRange);
+  
+  NewDecl->setQualifierInfo(NewQualifierLoc);
   return false;
 }
 
@@ -642,12 +642,12 @@
   // Instantiate the qualifier.  We have to do this first in case
   // we're a friend declaration, because if we are then we need to put
   // the new declaration in the appropriate context.
-  NestedNameSpecifier *Qualifier = Pattern->getQualifier();
-  if (Qualifier) {
-    Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
-                                                 Pattern->getQualifierRange(),
-                                                 TemplateArgs);
-    if (!Qualifier) return 0;
+  NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+                                                       TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
   }
 
   CXXRecordDecl *PrevDecl = 0;
@@ -668,9 +668,9 @@
   // the appropriate context.
   DeclContext *DC = Owner;
   if (isFriend) {
-    if (Qualifier) {
+    if (QualifierLoc) {
       CXXScopeSpec SS;
-      SS.MakeTrivial(SemaRef.Context, Qualifier, Pattern->getQualifierRange());
+      SS.Adopt(QualifierLoc);
       DC = SemaRef.computeDeclContext(SS);
       if (!DC) return 0;
     } else {
@@ -691,10 +691,10 @@
         PrevDecl = PrevClassTemplate->getTemplatedDecl();
     }
 
-    if (!PrevClassTemplate && Qualifier) {
+    if (!PrevClassTemplate && QualifierLoc) {
       SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
         << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
-        << Pattern->getQualifierRange();
+        << QualifierLoc.getSourceRange();
       return 0;
     }
 
@@ -755,8 +755,8 @@
                             Pattern->getTagKeywordLoc(), PrevDecl,
                             /*DelayTypeCreation=*/true);
 
-  if (Qualifier)
-    RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange());
+  if (QualifierLoc)
+    RecordInst->setQualifierInfo(QualifierLoc);
 
   ClassTemplateDecl *Inst
     = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
@@ -968,12 +968,12 @@
     return 0;
   QualType T = TInfo->getType();
 
-  NestedNameSpecifier *Qualifier = D->getQualifier();
-  if (Qualifier) {
-    Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
-                                                 D->getQualifierRange(),
-                                                 TemplateArgs);
-    if (!Qualifier) return 0;
+  NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+                                                       TemplateArgs);
+    if (!QualifierLoc)
+      return 0;
   }
 
   // If we're instantiating a local function declaration, put the result
@@ -981,9 +981,9 @@
   DeclContext *DC;
   if (D->getDeclContext()->isFunctionOrMethod())
     DC = Owner;
-  else if (isFriend && Qualifier) {
+  else if (isFriend && QualifierLoc) {
     CXXScopeSpec SS;
-    SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange());
+    SS.Adopt(QualifierLoc);
     DC = SemaRef.computeDeclContext(SS);
     if (!DC) return 0;
   } else {
@@ -997,8 +997,8 @@
                            D->getStorageClass(), D->getStorageClassAsWritten(),
                            D->isInlineSpecified(), D->hasWrittenPrototype());
 
-  if (Qualifier)
-    Function->setQualifierInfo(Qualifier, D->getQualifierRange());
+  if (QualifierLoc)
+    Function->setQualifierInfo(QualifierLoc);
 
   DeclContext *LexicalDC = Owner;
   if (!isFriend && D->isOutOfLine()) {
@@ -1260,19 +1260,19 @@
       return 0;    
   }
 
-  NestedNameSpecifier *Qualifier = D->getQualifier();
-  if (Qualifier) {
-    Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
-                                                 D->getQualifierRange(),
+  NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+  if (QualifierLoc) {
+    QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
                                                  TemplateArgs);
-    if (!Qualifier) return 0;
+    if (!QualifierLoc) 
+      return 0;
   }
 
   DeclContext *DC = Owner;
   if (isFriend) {
-    if (Qualifier) {
+    if (QualifierLoc) {
       CXXScopeSpec SS;
-      SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange());
+      SS.Adopt(QualifierLoc);
       DC = SemaRef.computeDeclContext(SS);
 
       if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
@@ -1315,8 +1315,8 @@
                                    D->isInlineSpecified());
   }
 
-  if (Qualifier)
-    Method->setQualifierInfo(Qualifier, D->getQualifierRange());
+  if (QualifierLoc)
+    Method->setQualifierInfo(QualifierLoc);
 
   if (TemplateParams) {
     // Our resulting instantiation is actually a function template, since we
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index fa0c2b9..641df42 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -385,6 +385,17 @@
                                               QualType ObjectType = QualType(),
                                           NamedDecl *FirstQualifierInScope = 0);
 
+  /// \brief Transform the given nested-name-specifier with source-location
+  /// information.
+  ///
+  /// By default, transforms all of the types and declarations within the
+  /// nested-name-specifier. Subclasses may override this function to provide
+  /// alternate behavior.
+  NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
+                                                    NestedNameSpecifierLoc NNS,
+                                          QualType ObjectType = QualType(),
+                                          NamedDecl *FirstQualifierInScope = 0);
+
   /// \brief Transform the given declaration name.
   ///
   /// By default, transforms the types of conversion function, constructor,
@@ -2264,6 +2275,11 @@
                                              QualType ObjectType,
                                              NamedDecl *FirstQualifierInScope,
                                              NestedNameSpecifier *Prefix);
+  
+  TypeLoc TransformTypeInObjectScope(TypeLoc TL,
+                                     QualType ObjectType,
+                                     NamedDecl *FirstQualifierInScope,
+                                     CXXScopeSpec &SS);
 };
 
 template<typename Derived>
@@ -2504,6 +2520,105 @@
 }
 
 template<typename Derived>
+NestedNameSpecifierLoc
+TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
+                                                    NestedNameSpecifierLoc NNS,
+                                                     QualType ObjectType,
+                                             NamedDecl *FirstQualifierInScope) {
+  llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+  for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; 
+       Qualifier = Qualifier.getPrefix())
+    Qualifiers.push_back(Qualifier);
+
+  CXXScopeSpec SS;
+  while (!Qualifiers.empty()) {
+    NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+    NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
+    
+    switch (QNNS->getKind()) {
+    case NestedNameSpecifier::Identifier:
+      if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0, 
+                                              *QNNS->getAsIdentifier(),
+                                              Q.getLocalBeginLoc(), 
+                                              Q.getLocalEndLoc(),
+                                              ObjectType, false, SS, 
+                                              FirstQualifierInScope, false))
+        return NestedNameSpecifierLoc();
+        
+      break;
+      
+    case NestedNameSpecifier::Namespace: {
+      NamespaceDecl *NS
+        = cast_or_null<NamespaceDecl>(
+                                    getDerived().TransformDecl(
+                                                          Q.getLocalBeginLoc(),
+                                                       QNNS->getAsNamespace()));
+      SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
+      break;
+    }
+      
+    case NestedNameSpecifier::NamespaceAlias: {
+      NamespaceAliasDecl *Alias
+        = cast_or_null<NamespaceAliasDecl>(
+                      getDerived().TransformDecl(Q.getLocalBeginLoc(),
+                                                 QNNS->getAsNamespaceAlias()));
+      SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), 
+                Q.getLocalEndLoc());
+      break;
+    }
+      
+    case NestedNameSpecifier::Global:
+      // There is no meaningful transformation that one could perform on the
+      // global scope.
+      SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
+      break;
+      
+    case NestedNameSpecifier::TypeSpecWithTemplate:
+    case NestedNameSpecifier::TypeSpec: {
+      TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
+                                              FirstQualifierInScope, SS);
+      
+      if (!TL)
+        return NestedNameSpecifierLoc();
+      
+      if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
+          (SemaRef.getLangOptions().CPlusPlus0x && 
+           TL.getType()->isEnumeralType())) {
+        assert(!TL.getType().hasLocalQualifiers() && 
+               "Can't get cv-qualifiers here");
+        SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL,
+                  Q.getLocalEndLoc());
+        break;
+      }
+      
+      SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) 
+        << TL.getType() << SS.getRange();
+      return NestedNameSpecifierLoc();
+    }
+  }
+    
+    // The object type and qualifier-in-scope really apply to the
+    // leftmost entity.
+    ObjectType = QualType();
+    FirstQualifierInScope = 0;
+  }
+  
+  // Don't rebuild the nested-name-specifier if we don't have to.
+  if (SS.getScopeRep() == NNS.getNestedNameSpecifier() && 
+      !getDerived().AlwaysRebuild())
+    return NNS;
+  
+  // If we can re-use the source-location data from the original 
+  // nested-name-specifier, do so.
+  if (SS.location_size() == NNS.getDataLength() &&
+      memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0)
+    return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData());
+
+  // Allocate new nested-name-specifier location information.
+  return SS.getWithLocInContext(SemaRef.Context);
+}
+
+template<typename Derived>
 DeclarationNameInfo
 TreeTransform<Derived>
 ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
@@ -3099,7 +3214,7 @@
                                                    QualType ObjectType,
                                                    NamedDecl *UnqualLookup,
                                                   NestedNameSpecifier *Prefix) {
-  // TODO: in some cases, we might be some verification to do here.
+  // TODO: in some cases, we might have some verification to do here.
   if (ObjectType.isNull())
     return getDerived().TransformType(TSI);
 
@@ -3136,6 +3251,62 @@
   return TLB.getTypeSourceInfo(SemaRef.Context, Result);
 }
 
+template<typename Derived>
+TypeLoc
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+                                                   QualType ObjectType,
+                                                   NamedDecl *UnqualLookup,
+                                                   CXXScopeSpec &SS) {
+  // FIXME: Painfully copy-paste from the above!
+  
+  // TODO: in some cases, we might have some verification to do here.
+  if (ObjectType.isNull()) {
+    TypeLocBuilder TLB;
+    TLB.reserve(TL.getFullDataSize());
+    QualType Result = getDerived().TransformType(TLB, TL);
+    if (Result.isNull())
+      return TypeLoc();
+    
+    return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+  }
+  
+  QualType T = TL.getType();
+  if (getDerived().AlreadyTransformed(T))
+    return TL;
+  
+  TypeLocBuilder TLB;
+  QualType Result;
+  
+  if (isa<TemplateSpecializationType>(T)) {
+    TemplateSpecializationTypeLoc SpecTL
+      = cast<TemplateSpecializationTypeLoc>(TL);
+    
+    TemplateName Template =
+      getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(),
+                                         ObjectType, UnqualLookup);
+    if (Template.isNull()) 
+      return TypeLoc();
+    
+    Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, 
+                                                              Template);
+  } else if (isa<DependentTemplateSpecializationType>(T)) {
+    DependentTemplateSpecializationTypeLoc SpecTL
+      = cast<DependentTemplateSpecializationTypeLoc>(TL);
+    
+    Result = getDerived().TransformDependentTemplateSpecializationType(TLB, 
+                                                                       SpecTL, 
+                                                             SS.getScopeRep());
+  } else {
+    // Nothing special needs to be done for these.
+    Result = getDerived().TransformType(TLB, TL);
+  }
+  
+  if (Result.isNull()) 
+    return TypeLoc();
+  
+  return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+}
+
 template <class TyLoc> static inline
 QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
   TyLoc NewT = TLB.push<TyLoc>(T.getType());
@@ -4351,7 +4522,8 @@
   TemplateArgumentListInfo NewTemplateArgs;
   NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
   NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
-            
+      
+  // FIXME: Nested-name-specifier source location info!
   typedef TemplateArgumentLocContainerIterator<
                             DependentTemplateSpecializationTypeLoc> ArgIterator;
   if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),