]> granicus.if.org Git - clang/commitdiff
Added basic source locations to Elaborated and DependentName types.
authorAbramo Bagnara <abramo.bagnara@gmail.com>
Wed, 19 May 2010 21:37:53 +0000 (21:37 +0000)
committerAbramo Bagnara <abramo.bagnara@gmail.com>
Wed, 19 May 2010 21:37:53 +0000 (21:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104169 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/TypeLoc.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
lib/Parse/ParseDecl.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h

index ae478c8c8dd5211c6ab94aaddfa5d80f2917bc1d..ec9423664e2b90530f2b4497ba17af3c496a078d 100644 (file)
@@ -269,6 +269,16 @@ public:
     return TypeClass::classof(Ty);
   }
 
+  static bool classof(const TypeLoc *TL) {
+    return Derived::classofType(TL->getTypePtr());
+  }
+  static bool classof(const UnqualTypeLoc *TL) {
+    return Derived::classofType(TL->getTypePtr());
+  }
+  static bool classof(const Derived *TL) {
+    return true;
+  }
+
   TypeLoc getNextTypeLoc() const {
     return getNextTypeLoc(asDerived()->getInnerType());
   }
@@ -1188,18 +1198,110 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                          DecltypeType> {
 };
 
-// FIXME: locations for the nested name specifier;  at the very least,
-// a SourceRange.
-class ElaboratedTypeLoc :
-    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
-                                     ElaboratedTypeLoc,
-                                     ElaboratedType> {
+struct ElaboratedLocInfo {
+  SourceLocation KeywordLoc;
+  SourceRange QualifierRange;
+};
+
+class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+                                                 ElaboratedTypeLoc,
+                                                 ElaboratedType,
+                                                 ElaboratedLocInfo> {
+public:
+  SourceLocation getKeywordLoc() const {
+    return this->getLocalData()->KeywordLoc;
+  }
+  void setKeywordLoc(SourceLocation Loc) {
+    this->getLocalData()->KeywordLoc = Loc;
+  }
+
+  SourceRange getQualifierRange() const {
+    return this->getLocalData()->QualifierRange;
+  }
+  void setQualifierRange(SourceRange Range) {
+    this->getLocalData()->QualifierRange = Range;
+  }
+
+  SourceRange getSourceRange() const {
+    if (getKeywordLoc().isValid())
+      if (getQualifierRange().getEnd().isValid())
+        return SourceRange(getKeywordLoc(), getQualifierRange().getEnd());
+      else
+        return SourceRange(getKeywordLoc());
+    else
+      return getQualifierRange();
+  }
+
+  void initializeLocal(SourceLocation Loc) {
+    setKeywordLoc(Loc);
+    setQualifierRange(SourceRange(Loc));
+  }
+
+  TypeLoc getNamedTypeLoc() const {
+    return getInnerTypeLoc();
+  }
+
+  QualType getInnerType() const {
+    return getTypePtr()->getNamedType();
+  }
+
+  void copy(ElaboratedTypeLoc Loc) {
+    unsigned size = getFullDataSize();
+    assert(size == Loc.getFullDataSize());
+    memcpy(Data, Loc.Data, size);
+  }
 };
 
-// FIXME: locations for the typename keyword and nested name specifier.
-class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
-                                                         DependentNameTypeLoc,
-                                                         DependentNameType> {
+struct DependentNameLocInfo {
+  SourceLocation KeywordLoc;
+  SourceRange QualifierRange;
+  SourceLocation NameLoc;
+};
+
+class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+                                                    DependentNameTypeLoc,
+                                                    DependentNameType,
+                                                    DependentNameLocInfo> {
+public:
+  SourceLocation getKeywordLoc() const {
+    return this->getLocalData()->KeywordLoc;
+  }
+  void setKeywordLoc(SourceLocation Loc) {
+    this->getLocalData()->KeywordLoc = Loc;
+  }
+
+  SourceRange getQualifierRange() const {
+    return this->getLocalData()->QualifierRange;
+  }
+  void setQualifierRange(SourceRange Range) {
+    this->getLocalData()->QualifierRange = Range;
+  }
+
+  SourceLocation getNameLoc() const {
+    return this->getLocalData()->NameLoc;
+  }
+  void setNameLoc(SourceLocation Loc) {
+    this->getLocalData()->NameLoc = Loc;
+  }
+
+  SourceRange getSourceRange() const {
+    if (getKeywordLoc().isValid())
+      return SourceRange(getKeywordLoc(), getNameLoc());
+    else
+      return SourceRange(getQualifierRange().getBegin(), getNameLoc());
+  }
+
+  void copy(DependentNameTypeLoc Loc) {
+    unsigned size = getFullDataSize();
+    assert(size == Loc.getFullDataSize());
+    memcpy(Data, Loc.Data, size);
+  }
+
+  void initializeLocal(SourceLocation Loc) {
+    setKeywordLoc(Loc);
+    setQualifierRange(SourceRange(Loc));
+    setNameLoc(Loc);
+  }
 };
 
 }
index cca434ea8baff1d8981e9c5b3e6de7d6bb6d46c0..88e9b9db18054677c12470b3a2854175cfaa4d0c 100644 (file)
@@ -2356,12 +2356,15 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc(
                                           Record, Idx));
 }
 void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx));
 }
 void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
 void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+  TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx));
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
 void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
index f8415cd0529d489a1a784e92754aab6ef71fd1f4..6887d847e9816c03dacddc769b3a601f002044cb 100644 (file)
@@ -397,12 +397,15 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
     Writer.AddTemplateArgumentLoc(TL.getArgLoc(i), Record);
 }
 void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
-  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+  Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
+  Writer.AddSourceRange(TL.getQualifierRange(), Record);
 }
 void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
 void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getKeywordLoc(), Record);
+  Writer.AddSourceRange(TL.getQualifierRange(), Record);
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
 void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
index 929b20cc3d46d98d69e7bf8aeaadab2421c766eb..ec485d2d964682d7d7569bb44c30537fac429a45 100644 (file)
@@ -1877,7 +1877,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
   if (Tok.is(tok::kw___attribute))
     Attr.reset(ParseGNUAttributes());
 
-  CXXScopeSpec SS;
+  CXXScopeSpec &SS = DS.getTypeSpecScope();
   if (getLang().CPlusPlus) {
     if (ParseOptionalCXXScopeSpecifier(SS, 0, false))
       return;
index ed639350e520e4d61e5ae0675d5ea1fc0386c0c0..4d9463f6523826e73197938e8c30d2d227fc87b1 100644 (file)
@@ -3117,7 +3117,9 @@ public:
   QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
                              NestedNameSpecifier *NNS,
                              const IdentifierInfo &II,
-                             SourceRange Range);
+                             SourceLocation KeywordLoc,
+                             SourceRange NNSRange,
+                             SourceLocation IILoc);
 
   TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
                                                     SourceLocation Loc,
index e0151d310100e1f071ea1620d5df21852fbf7bd5..30eaee423bd5c90a27dd4b112c23682a5a1bd41c 100644 (file)
@@ -90,8 +90,9 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
         // 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;
index 7fcc6ea886da3dead15c06926f36637ab6a10a0e..6682c661167673cbe442b700d118d40655909e07 100644 (file)
@@ -1136,7 +1136,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
           // 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;
 
index f38bb1c96db514b91687361c1ada63e07b0230c0..0737e9f151a6566c014d350b6c69077f64a2c6c9 100644 (file)
@@ -261,7 +261,8 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
       Range = SourceRange(NameLoc);
     }
 
-    return CheckTypenameType(ETK_None, NNS, II, Range).getAsOpaquePtr();
+    return CheckTypenameType(ETK_None, NNS, II, SourceLocation(),
+                             Range, NameLoc).getAsOpaquePtr();
   }
 
   if (ObjectTypePtr)
index 9009b4d89773bfc54f8ec8e246d1f8671b12519f..5c908a00f681b35d6065b73b2e64fa508e63dd48 100644 (file)
@@ -5184,16 +5184,19 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
 
 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 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
     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 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
   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 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
   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 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
 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 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
     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 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
 
   // 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 @@ CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB,
 
   NestedNameSpecifier *NNS
     = TransformNestedNameSpecifier(T->getQualifier(),
-                                   /*FIXME:*/SourceRange(getBaseLocation()),
+                                   TL.getQualifierRange(),
                                    ObjectType);
   if (!NNS)
     return QualType();
@@ -5402,7 +5408,7 @@ CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB,
   // 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 @@ CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB,
         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;
 }
 
index 9ade954375d239465cef64ebe2841eb80bafb433..80fafb6ad25ca7734f37edb677ac9011c1dd43e4 100644 (file)
@@ -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 @@ namespace {
         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 @@ namespace {
           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 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
   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)
index a8120b85cddb20723377f691fa41bce0950126d8..69994cd1d2f919c672dd6307dfcd7378ed19d166 100644 (file)
@@ -530,10 +530,9 @@ public:
 
   /// \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 @@ public:
   /// \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 @@ public:
     }
 
     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 @@ public:
 
     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 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
   // 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 TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
                                                        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 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
         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;
 }