Added basic source locations to Elaborated and DependentName types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104169 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ed63935..4d9463f 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3117,7 +3117,9 @@
   QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS,
                              const IdentifierInfo &II,
-                             SourceRange Range);
+                             SourceLocation KeywordLoc,
+                             SourceRange NNSRange,
+                             SourceLocation IILoc);
 
   TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
                                                     SourceLocation Loc,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e0151d3..30eaee4 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -90,8 +90,9 @@
         // We know from the grammar that this name refers to a type, so build a
         // DependentNameType node to describe the type.
         return CheckTypenameType(ETK_None,
-                                 (NestedNameSpecifier *)SS->getScopeRep(),
-                                 II, SS->getRange()).getAsOpaquePtr();
+                                 (NestedNameSpecifier *)SS->getScopeRep(), II,
+                                 SourceLocation(), SS->getRange(), NameLoc
+                                 ).getAsOpaquePtr();
       }
       
       return 0;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 7fcc6ea..6682c66 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1136,7 +1136,8 @@
           // specialization, we take it as a type name.
           BaseType = CheckTypenameType(ETK_None,
                                        (NestedNameSpecifier *)SS.getScopeRep(),
-                                       *MemberOrBase, SS.getRange());
+                                       *MemberOrBase, SourceLocation(),
+                                       SS.getRange(), IdLoc);
           if (BaseType.isNull())
             return true;
 
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index f38bb1c..0737e9f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -261,7 +261,8 @@
       Range = SourceRange(NameLoc);
     }
 
-    return CheckTypenameType(ETK_None, NNS, II, Range).getAsOpaquePtr();
+    return CheckTypenameType(ETK_None, NNS, II, SourceLocation(),
+                             Range, NameLoc).getAsOpaquePtr();
   }
 
   if (ObjectTypePtr)
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 9009b4d..5c908a0 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -5184,16 +5184,19 @@
 
 static void FillTypeLoc(DependentNameTypeLoc TL,
                         SourceLocation TypenameLoc,
-                        SourceRange QualifierRange) {
-  // FIXME: typename, qualifier range
-  TL.setNameLoc(TypenameLoc);
+                        SourceRange QualifierRange,
+                        SourceLocation NameLoc) {
+  TL.setKeywordLoc(TypenameLoc);
+  TL.setQualifierRange(QualifierRange);
+  TL.setNameLoc(NameLoc);
 }
 
 static void FillTypeLoc(ElaboratedTypeLoc TL,
                         SourceLocation TypenameLoc,
                         SourceRange QualifierRange) {
-  // FIXME: typename, qualifier range
-  TL.setNameLoc(TypenameLoc);
+  // FIXME: inner locations.
+  TL.setKeywordLoc(TypenameLoc);
+  TL.setQualifierRange(QualifierRange);
 }
 
 Sema::TypeResult
@@ -5205,7 +5208,7 @@
     return true;
 
   QualType T = CheckTypenameType(ETK_Typename, NNS, II,
-                                 SourceRange(TypenameLoc, IdLoc));
+                                 TypenameLoc, SS.getRange(), IdLoc);
   if (T.isNull())
     return true;
 
@@ -5213,7 +5216,7 @@
   if (isa<DependentNameType>(T)) {
     DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
     // FIXME: fill inner type loc
-    FillTypeLoc(TL, TypenameLoc, SS.getRange());
+    FillTypeLoc(TL, TypenameLoc, SS.getRange(), IdLoc);
   } else {
     ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
     // FIXME: fill inner type loc
@@ -5249,7 +5252,7 @@
   TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
   DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
   // FIXME: fill inner type loc
-  FillTypeLoc(TL, TypenameLoc, SS.getRange());
+  FillTypeLoc(TL, TypenameLoc, SS.getRange(), TemplateLoc);
   return CreateLocInfoType(T, TSI).getAsOpaquePtr();
 }
 
@@ -5258,10 +5261,11 @@
 QualType
 Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
                         NestedNameSpecifier *NNS, const IdentifierInfo &II,
-                        SourceRange Range) {
+                        SourceLocation KeywordLoc, SourceRange NNSRange,
+                        SourceLocation IILoc) {
   CXXScopeSpec SS;
   SS.setScopeRep(NNS);
-  SS.setRange(Range);
+  SS.setRange(NNSRange);
 
   DeclContext *Ctx = computeDeclContext(SS);
   if (!Ctx) {
@@ -5281,7 +5285,7 @@
     return QualType();
 
   DeclarationName Name(&II);
-  LookupResult Result(*this, Name, Range.getEnd(), LookupOrdinaryName);
+  LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
   LookupQualifiedName(Result, Ctx);
   unsigned DiagID = 0;
   Decl *Referenced = 0;
@@ -5321,7 +5325,9 @@
 
   // If we get here, it's because name lookup did not find a
   // type. Emit an appropriate diagnostic and return an error.
-  Diag(Range.getEnd(), DiagID) << Range << Name << Ctx;
+  SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : NNSRange.getBegin(),
+                        IILoc);
+  Diag(IILoc, DiagID) << FullRange << Name << Ctx;
   if (Referenced)
     Diag(Referenced->getLocation(), diag::note_typename_refers_here)
       << Name;
@@ -5393,7 +5399,7 @@
 
   NestedNameSpecifier *NNS
     = TransformNestedNameSpecifier(T->getQualifier(),
-                                   /*FIXME:*/SourceRange(getBaseLocation()),
+                                   TL.getQualifierRange(),
                                    ObjectType);
   if (!NNS)
     return QualType();
@@ -5402,7 +5408,7 @@
   // context corresponding to the nested-name-specifier, then this
   // typename type will not change; exit early.
   CXXScopeSpec SS;
-  SS.setRange(SourceRange(getBaseLocation()));
+  SS.setRange(TL.getQualifierRange());
   SS.setScopeRep(NNS);
 
   QualType Result;
@@ -5421,18 +5427,38 @@
         NewTemplateId == QualType(TemplateId, 0))
       Result = QualType(T, 0);
     else
-      Result = getDerived().RebuildDependentNameType(T->getKeyword(), 
+      Result = getDerived().RebuildDependentNameType(T->getKeyword(),
                                                      NNS, NewTemplateId);
   } else
-    Result = getDerived().RebuildDependentNameType(T->getKeyword(),
-                                                   NNS, T->getIdentifier(),
-                                                  SourceRange(TL.getNameLoc()));
+    Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
+                                                   T->getIdentifier(),
+                                                   TL.getKeywordLoc(),
+                                                   TL.getQualifierRange(),
+                                                   TL.getNameLoc());
 
   if (Result.isNull())
     return QualType();
 
-  DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
+  if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
+    QualType NamedT = ElabT->getNamedType();
+    if (isa<TemplateSpecializationType>(NamedT)) {
+      TemplateSpecializationTypeLoc NamedTLoc
+        = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+      // FIXME: fill locations
+      NamedTLoc.initializeLocal(TL.getNameLoc());
+    } else {
+      TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
+    }
+    ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+    NewTL.setKeywordLoc(TL.getKeywordLoc());
+    NewTL.setQualifierRange(TL.getQualifierRange());
+  }
+  else {
+    DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
+    NewTL.setKeywordLoc(TL.getKeywordLoc());
+    NewTL.setQualifierRange(TL.getQualifierRange());
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
   return Result;
 }
 
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9ade954..80fafb6 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -25,6 +25,8 @@
 #include "llvm/Support/ErrorHandling.h"
 using namespace clang;
 
+#include <iostream>
+
 /// \brief Perform adjustment on the parameter type of a function.
 ///
 /// This routine adjusts the given parameter type @p T to the actual
@@ -1437,9 +1439,15 @@
         return;
       }
 
-      TemplateSpecializationTypeLoc OldTL =
-        cast<TemplateSpecializationTypeLoc>(TInfo->getTypeLoc());
-      TL.copy(OldTL);
+      TypeLoc OldTL = TInfo->getTypeLoc();
+      if (TInfo->getType()->getAs<ElaboratedType>()) {
+        ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
+        TemplateSpecializationTypeLoc NamedTL =
+          cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
+        TL.copy(NamedTL);
+      }
+      else
+        TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
     }
     void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
       assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
@@ -1470,6 +1478,44 @@
           TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
       }
     }
+    void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+      ElaboratedTypeKeyword Keyword
+        = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+      if (Keyword == ETK_Typename) {
+        TypeSourceInfo *TInfo = 0;
+        Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+        if (TInfo) {
+          TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
+          return;
+        }
+      }
+      TL.setKeywordLoc(Keyword != ETK_None
+                       ? DS.getTypeSpecTypeLoc()
+                       : SourceLocation());
+      const CXXScopeSpec& SS = DS.getTypeSpecScope();
+      TL.setQualifierRange(SS.isEmpty() ? SourceRange(): SS.getRange());
+      Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
+    }
+    void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+      ElaboratedTypeKeyword Keyword
+        = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+      if (Keyword == ETK_Typename) {
+        TypeSourceInfo *TInfo = 0;
+        Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+        if (TInfo) {
+          TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
+          return;
+        }
+      }
+      TL.setKeywordLoc(Keyword != ETK_None
+                       ? DS.getTypeSpecTypeLoc()
+                       : SourceLocation());
+      const CXXScopeSpec& SS = DS.getTypeSpecScope();
+      TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
+      // FIXME: load appropriate source location.
+      TL.setNameLoc(DS.getTypeSpecTypeLoc());
+    }
+
     void VisitTypeLoc(TypeLoc TL) {
       // FIXME: add other typespec types and change this to an assert.
       TL.initialize(DS.getTypeSpecTypeLoc());
@@ -2081,7 +2127,7 @@
   if (T.isNull())
     return T;
   NestedNameSpecifier *NNS;
-  if (SS.isSet() && !SS.isInvalid())
+  if (SS.isValid())
     NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
   else {
     if (Keyword == ETK_None)
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index a8120b8..69994cd 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -530,10 +530,9 @@
 
   /// \brief Build a new typename type that refers to a template-id.
   ///
-  /// By default, builds a new DependentNameType type from the 
-  /// nested-name-specifier
-  /// and the given type. Subclasses may override this routine to provide
-  /// different behavior.
+  /// By default, builds a new DependentNameType type from the
+  /// nested-name-specifier and the given type. Subclasses may override
+  /// this routine to provide different behavior.
   QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
                                     NestedNameSpecifier *NNS, QualType T) {
     if (NNS->isDependent()) {
@@ -551,15 +550,18 @@
   /// \brief Build a new typename type that refers to an identifier.
   ///
   /// By default, performs semantic analysis when building the typename type
-  /// (or qualified name type). Subclasses may override this routine to provide
+  /// (or elaborated type). Subclasses may override this routine to provide
   /// different behavior.
-  QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, 
+  QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
                                     NestedNameSpecifier *NNS,
                                     const IdentifierInfo *Id,
-                                    SourceRange SR) {
+                                    SourceLocation KeywordLoc,
+                                    SourceRange NNSRange,
+                                    SourceLocation IdLoc) {
     CXXScopeSpec SS;
     SS.setScopeRep(NNS);
-    
+    SS.setRange(NNSRange);
+
     if (NNS->isDependent()) {
       // If the name is still dependent, just build a new dependent name type.
       if (!SemaRef.computeDeclContext(SS))
@@ -567,14 +569,15 @@
     }
 
     if (Keyword == ETK_None || Keyword == ETK_Typename)
-      return SemaRef.CheckTypenameType(Keyword, NNS, *Id, SR);
+      return SemaRef.CheckTypenameType(Keyword, NNS, *Id,
+                                       KeywordLoc, NNSRange, IdLoc);
 
     TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
 
-    // We had a dependent elaborated-type-specifier that as been transformed
+    // We had a dependent elaborated-type-specifier that has been transformed
     // into a non-dependent elaborated-type-specifier. Find the tag we're
     // referring to.
-    LookupResult Result(SemaRef, Id, SR.getEnd(), Sema::LookupTagName);
+    LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName);
     DeclContext *DC = SemaRef.computeDeclContext(SS, false);
     if (!DC)
       return QualType();
@@ -602,14 +605,13 @@
 
     if (!Tag) {
       // FIXME: Would be nice to highlight just the source range.
-      SemaRef.Diag(SR.getEnd(), diag::err_not_tag_in_scope)
+      SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope)
         << Kind << Id << DC;
       return QualType();
     }
 
-    // FIXME: Terrible location information
-    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, SR.getEnd(), *Id)) {
-      SemaRef.Diag(SR.getBegin(), diag::err_use_with_wrong_tag) << Id;
+    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, IdLoc, *Id)) {
+      SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id;
       SemaRef.Diag(Tag->getLocation(), diag::note_previous_use);
       return QualType();
     }
@@ -3237,27 +3239,45 @@
   // NOTE: the qualifier in an ElaboratedType is optional.
   if (T->getQualifier() != 0) {
     NNS = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
-                                                    SourceRange(),
+                                                    TL.getQualifierRange(),
                                                     ObjectType);
     if (!NNS)
       return QualType();
   }
 
-  QualType Named = getDerived().TransformType(T->getNamedType());
-  if (Named.isNull())
-    return QualType();
+  QualType NamedT;
+  // FIXME: this test is meant to workaround a problem (failing assertion)
+  // occurring if directly executing the code in the else branch.
+  if (isa<TemplateSpecializationTypeLoc>(TL.getNamedTypeLoc())) {
+    TemplateSpecializationTypeLoc OldNamedTL
+      = cast<TemplateSpecializationTypeLoc>(TL.getNamedTypeLoc());
+    const TemplateSpecializationType* OldTST
+      = OldNamedTL.getType()->getAs<TemplateSpecializationType>();
+    NamedT = TransformTemplateSpecializationType(OldTST, ObjectType);
+    if (NamedT.isNull())
+      return QualType();
+    TemplateSpecializationTypeLoc NewNamedTL
+      = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+    NewNamedTL.copy(OldNamedTL);
+  }
+  else {
+    NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
+    if (NamedT.isNull())
+      return QualType();
+  }
 
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
       NNS != T->getQualifier() ||
-      Named != T->getNamedType()) {
-    Result = getDerived().RebuildElaboratedType(T->getKeyword(), NNS, Named);
+      NamedT != T->getNamedType()) {
+    Result = getDerived().RebuildElaboratedType(T->getKeyword(), NNS, NamedT);
     if (Result.isNull())
       return QualType();
   }
 
   ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
+  NewTL.setKeywordLoc(TL.getKeywordLoc());
+  NewTL.setQualifierRange(TL.getQualifierRange());
 
   return Result;
 }
@@ -3268,11 +3288,9 @@
                                                        QualType ObjectType) {
   DependentNameType *T = TL.getTypePtr();
 
-  /* FIXME: preserve source information better than this */
-  SourceRange SR(TL.getNameLoc());
-
   NestedNameSpecifier *NNS
-    = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR,
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+                                                TL.getQualifierRange(),
                                                 ObjectType);
   if (!NNS)
     return QualType();
@@ -3290,18 +3308,38 @@
         NewTemplateId == QualType(TemplateId, 0))
       return QualType(T, 0);
 
-    Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, 
+    Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
                                                    NewTemplateId);
   } else {
-    Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, 
-                                                   T->getIdentifier(), SR);
+    Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
+                                                   T->getIdentifier(),
+                                                   TL.getKeywordLoc(),
+                                                   TL.getQualifierRange(),
+                                                   TL.getNameLoc());
   }
   if (Result.isNull())
     return QualType();
 
-  DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
-
+  if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
+    QualType NamedT = ElabT->getNamedType();
+    if (isa<TemplateSpecializationType>(NamedT)) {
+      TemplateSpecializationTypeLoc NamedTLoc
+        = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+      // FIXME: fill locations
+      NamedTLoc.initializeLocal(TL.getNameLoc());
+    } else {
+      TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
+    }
+    ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+    NewTL.setKeywordLoc(TL.getKeywordLoc());
+    NewTL.setQualifierRange(TL.getQualifierRange());
+  }
+  else {
+    DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
+    NewTL.setKeywordLoc(TL.getKeywordLoc());
+    NewTL.setQualifierRange(TL.getQualifierRange());
+    NewTL.setNameLoc(TL.getNameLoc());
+  }
   return Result;
 }