Fix "using typename" and the instantiation of non-dependent using declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90614 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a63db14..94f2fdc 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -260,24 +260,40 @@
}
NamedDecl *
-ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
+ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
- = InstantiatedFromUnresolvedUsingDecl.find(UUD);
- if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
+ = InstantiatedFromUsingDecl.find(UUD);
+ if (Pos == InstantiatedFromUsingDecl.end())
return 0;
return Pos->second;
}
void
-ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
- NamedDecl *UUD) {
- assert((isa<UnresolvedUsingValueDecl>(UUD) ||
- isa<UnresolvedUsingTypenameDecl>(UUD)) &&
- "original declaration is not an unresolved using decl");
- assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
- "Already noted what using decl what instantiated from");
- InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
+ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+ assert((isa<UsingDecl>(Pattern) ||
+ isa<UnresolvedUsingValueDecl>(Pattern) ||
+ isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
+ "pattern decl is not a using decl");
+ assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingDecl[Inst] = Pattern;
+}
+
+UsingShadowDecl *
+ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
+ llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
+ = InstantiatedFromUsingShadowDecl.find(Inst);
+ if (Pos == InstantiatedFromUsingShadowDecl.end())
+ return 0;
+
+ return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+ UsingShadowDecl *Pattern) {
+ assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingShadowDecl[Inst] = Pattern;
}
FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
@@ -1766,6 +1782,9 @@
Decl->TypeForDecl = PrevDecl->TypeForDecl;
else
Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
+ } else if (UnresolvedUsingTypenameDecl *Using =
+ dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
+ Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
} else
assert(false && "TypeDecl without a type?");
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 50a5120..3ccb7a9 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -94,3 +94,32 @@
TypeLocInitializer(Loc).Visit(TL);
} while ((TL = TL.getNextTypeLoc()));
}
+
+namespace {
+ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class. Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+ if (TL->getType().hasLocalQualifiers()) return false;
+ return TSTChecker().Visit(*TL);
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 3d7a537..2f58ebe 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -303,6 +303,15 @@
Print(T->getResultType(), S);
}
+void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
+ std::string &S) {
+ IdentifierInfo *II = T->getDecl()->getIdentifier();
+ if (S.empty())
+ S = II->getName().str();
+ else
+ S = II->getName().str() + ' ' + S;
+}
+
void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) {
if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
S = ' ' + S;
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 4d021e8..df708ed 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -843,6 +843,12 @@
// <type> ::= <class-enum-type>
// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
void CXXNameMangler::mangleType(const EnumType *T) {
mangleType(static_cast<const TagType*>(T));
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 40eb9ca..811f9ed 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1880,6 +1880,10 @@
Exceptions.data());
}
+ case pch::TYPE_UNRESOLVED_USING:
+ return Context->getTypeDeclType(
+ cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
case pch::TYPE_TYPEDEF:
assert(Record.size() == 1 && "incorrect encoding of typedef type");
return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
@@ -2044,6 +2048,9 @@
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e79f9c9..0e6d1d2 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -166,6 +166,14 @@
Code = pch::TYPE_FUNCTION_PROTO;
}
+#if 0
+// For when we want it....
+void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = pch::TYPE_UNRESOLVED_USING;
+}
+#endif
+
void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
Code = pch::TYPE_TYPEDEF;
@@ -337,6 +345,9 @@
void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 616151e..9606821 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1729,6 +1729,10 @@
SourceLocation IdentLoc,
IdentifierInfo *Ident);
+ bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc);
+
NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 58b5633..992bb80 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2900,10 +2900,8 @@
TargetName, AttrList,
/* IsInstantiation */ false,
IsTypeName, TypenameLoc);
- if (UD) {
- PushOnScopeChains(UD, S);
- UD->setAccess(AS);
- }
+ if (UD)
+ PushOnScopeChains(UD, S, /*AddToContext*/ false);
return DeclPtrTy::make(UD);
}
@@ -2962,19 +2960,33 @@
NestedNameSpecifier *NNS =
static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+ return 0;
+
DeclContext *LookupContext = computeDeclContext(SS);
+ NamedDecl *D;
if (!LookupContext) {
if (IsTypeName) {
- return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
- UsingLoc, TypenameLoc,
- SS.getRange(), NNS,
- IdentLoc, Name);
- } else {
- return UnresolvedUsingValueDecl::Create(Context, CurContext,
- UsingLoc, SS.getRange(), NNS,
+ // FIXME: not all declaration name kinds are legal here
+ D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+ UsingLoc, TypenameLoc,
+ SS.getRange(), NNS,
IdentLoc, Name);
+ } else {
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext,
+ UsingLoc, SS.getRange(), NNS,
+ IdentLoc, Name);
}
+ } else {
+ D = UsingDecl::Create(Context, CurContext, IdentLoc,
+ SS.getRange(), UsingLoc, NNS, Name,
+ IsTypeName);
}
+ D->setAccess(AS);
+ CurContext->addDecl(D);
+
+ if (!LookupContext) return D;
+ UsingDecl *UD = cast<UsingDecl>(D);
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
// C++0x N2914 [namespace.udecl]p3:
@@ -2989,7 +3001,8 @@
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
<< NNS << RD->getDeclName();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
} else {
// C++0x N2914 [namespace.udecl]p8:
@@ -2997,7 +3010,8 @@
if (isa<CXXRecordDecl>(LookupContext)) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
}
@@ -3017,54 +3031,63 @@
if (R.empty()) {
Diag(IdentLoc, diag::err_no_member)
<< Name << LookupContext << SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
- if (R.isAmbiguous())
- return 0;
+ if (R.isAmbiguous()) {
+ UD->setInvalidDecl();
+ return UD;
+ }
if (IsTypeName) {
// If we asked for a typename and got a non-type decl, error out.
- if (R.getResultKind() != LookupResult::Found
- || !isa<TypeDecl>(R.getFoundDecl())) {
+ if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
diag::note_using_decl_target);
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
} else {
// If we asked for a non-typename and we got a type, error out,
// but only if this is an instantiation of an unresolved using
// decl. Otherwise just silently find the type name.
- if (IsInstantiation &&
- R.getResultKind() == LookupResult::Found &&
- isa<TypeDecl>(R.getFoundDecl())) {
+ if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_dependent_value_is_type);
Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
}
// C++0x N2914 [namespace.udecl]p6:
// A using-declaration shall not name a namespace.
- if (R.getResultKind() == LookupResult::Found
- && isa<NamespaceDecl>(R.getFoundDecl())) {
+ if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
- return 0;
+ UD->setInvalidDecl();
+ return UD;
}
- UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc,
- SS.getRange(), UsingLoc, NNS, Name,
- IsTypeName);
-
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
BuildUsingShadowDecl(*this, S, AS, UD, *I);
return UD;
}
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope. If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc) {
+ // FIXME: implement
+
+ return false;
+}
+
Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 613ffde..b4754db 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2361,6 +2361,7 @@
case Type::Enum:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::UnresolvedUsing:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 122e85e..6a4ac3c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1064,8 +1064,6 @@
Invalid = true;
} else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
Fields.push_back(DeclPtrTy::make(Field));
- else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
- Instantiation->addDecl(UD);
} else {
// FIXME: Eventually, a NULL return will mean that one of the
// instantiations was a semantic disaster, and we'll want to set Invalid =
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ec28f47..6b41d9a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -66,6 +66,8 @@
Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
@@ -1034,6 +1036,56 @@
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+ // The nested name specifier is non-dependent, so no transformation
+ // is required.
+
+ UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(),
+ D->getNestedNameRange(),
+ D->getUsingLocation(),
+ D->getTargetNestedNameDecl(),
+ D->getDeclName(),
+ D->isTypeName());
+
+ CXXScopeSpec SS;
+ SS.setScopeRep(D->getTargetNestedNameDecl());
+ SS.setRange(D->getNestedNameRange());
+ if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+ D->getLocation()))
+ NewUD->setInvalidDecl();
+ SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+ NewUD->setAccess(D->getAccess());
+ Owner->addDecl(NewUD);
+
+ // We'll transform the UsingShadowDecls as we reach them.
+
+ return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+ UsingDecl *InstUsing =
+ cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
+ TemplateArgs));
+ NamedDecl *InstTarget =
+ cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
+ TemplateArgs));
+
+ UsingShadowDecl *InstD = UsingShadowDecl::Create(SemaRef.Context, Owner,
+ InstUsing->getLocation(),
+ InstUsing, InstTarget);
+ InstUsing->addShadowDecl(InstD);
+
+ if (InstTarget->isInvalidDecl() || InstUsing->isInvalidDecl())
+ InstD->setInvalidDecl();
+
+ SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
+ InstD->setAccess(D->getAccess());
+ Owner->addDecl(InstD);
+
+ return InstD;
+}
+
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
NestedNameSpecifier *NNS =
@@ -1054,8 +1106,8 @@
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
- SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
- D);
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
return UD;
}
@@ -1079,8 +1131,8 @@
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
- SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
- D);
+ SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
return UD;
}
@@ -1753,16 +1805,28 @@
return false;
}
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+ UsingShadowDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+ UsingDecl *Instance,
+ ASTContext &C) {
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
}
static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
UsingDecl *Instance,
ASTContext &C) {
- return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+ return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
}
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -1780,6 +1844,8 @@
return false;
}
+// Other is the prospective instantiation
+// D is the prospective pattern
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (D->getKind() != Other->getKind()) {
if (UnresolvedUsingTypenameDecl *UUD
@@ -1831,6 +1897,12 @@
}
}
+ if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+ return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+ if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+ return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
return D->getDeclName() && isa<NamedDecl>(Other) &&
D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e1ac322..b029a37 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -461,6 +461,10 @@
/// \brief Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
+ /// \brief Rebuild an unresolved typename type, given the decl that
+ /// the UnresolvedUsingTypenameDecl was transformed to.
+ QualType RebuildUnresolvedUsingType(Decl *D);
+
/// \brief Build a new typedef type.
QualType RebuildTypedefType(TypedefDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
@@ -2578,6 +2582,29 @@
return Result;
}
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+ UnresolvedUsingTypeLoc TL) {
+ UnresolvedUsingType *T = TL.getTypePtr();
+ Decl *D = getDerived().TransformDecl(T->getDecl());
+ if (!D)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+ Result = getDerived().RebuildUnresolvedUsingType(D);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ // We might get an arbitrary type spec type back. We should at
+ // least always get a type spec type, though.
+ TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
TypedefTypeLoc TL) {
@@ -5318,6 +5345,30 @@
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+ assert(D && "no decl found");
+ if (D->isInvalidDecl()) return QualType();
+
+ TypeDecl *Ty;
+ if (isa<UsingDecl>(D)) {
+ UsingDecl *Using = cast<UsingDecl>(D);
+ assert(Using->isTypeName() &&
+ "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+ // A valid resolved using typename decl points to exactly one type decl.
+ assert(++Using->shadow_begin() == Using->shadow_end());
+ Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+
+ } else {
+ assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+ "UnresolvedUsingTypenameDecl transformed to non-using decl");
+ Ty = cast<UnresolvedUsingTypenameDecl>(D);
+ }
+
+ return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
}