When building and instantiating a template-id reference expression, such as
N::f<int>
keep track of the full nested-name-specifier. This is mainly QoI and
relatively hard to test; will try to come up with a printing-based
test once we also retain the explicit template arguments past overload
resolution.
llvm-svn: 84869
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index e636563..074a6fc 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2529,14 +2529,17 @@
DeclSpec::TST TagSpec,
SourceLocation TagLoc);
- OwningExprResult BuildTemplateIdExpr(TemplateName Template,
+ OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
- virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
+ virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c691cd9..0f22320 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1251,7 +1251,9 @@
return ElabType.getAsOpaquePtr();
}
-Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgument *TemplateArgs,
@@ -1267,28 +1269,30 @@
if (!D)
D = Template.getAsOverloadedFunctionDecl();
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
QualType ThisType, MemberType;
- if (D && isImplicitMemberReference(/*FIXME:??*/0, D, TemplateNameLoc,
+ if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc,
ThisType, MemberType)) {
Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
return Owned(MemberExpr::Create(Context, This, true,
- /*FIXME:*/0, /*FIXME:*/SourceRange(),
+ Qualifier, QualifierRange,
D, TemplateNameLoc, true,
LAngleLoc, TemplateArgs,
NumTemplateArgs, RAngleLoc,
Context.OverloadTy));
}
- return Owned(TemplateIdRefExpr::Create(Context,
- /*FIXME: New type?*/Context.OverloadTy,
- /*FIXME: Necessary?*/0,
- /*FIXME: Necessary?*/SourceRange(),
+ return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy,
+ Qualifier, QualifierRange,
Template, TemplateNameLoc, LAngleLoc,
TemplateArgs,
NumTemplateArgs, RAngleLoc));
}
-Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
+Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy TemplateD,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -1301,7 +1305,9 @@
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
TemplateArgsIn.release();
- return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc,
+ return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
+ SS.getRange(),
+ Template, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
RAngleLoc);
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 53aef9f..5f06ce5 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1445,13 +1445,16 @@
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildTemplateIdExpr(TemplateName Template,
+ OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
- return getSema().BuildTemplateIdExpr(Template, TemplateLoc,
+ return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
+ Template, TemplateLoc,
LAngleLoc,
TemplateArgs, NumTemplateArgs,
RAngleLoc);
@@ -4369,8 +4372,8 @@
TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
UnresolvedDeclRefExpr *E) {
NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
if (!NNS)
return SemaRef.ExprError();
@@ -4399,6 +4402,14 @@
if (Template.isNull())
return SemaRef.ExprError();
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+ }
+
llvm::SmallVector<TemplateArgument, 4> TransArgs;
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgument TransArg
@@ -4415,7 +4426,8 @@
// FIXME: It's possible that we'll find out now that the template name
// actually refers to a type, in which case the caller is actually dealing
// with a functional cast. Give a reasonable error message!
- return getDerived().RebuildTemplateIdExpr(Template, E->getTemplateNameLoc(),
+ return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(),
+ Template, E->getTemplateNameLoc(),
E->getLAngleLoc(),
TransArgs.data(),
TransArgs.size(),