summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp134
1 files changed, 98 insertions, 36 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8d370ce9063..8038a4502ab 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1559,7 +1559,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS, NamedDecl *FoundD) {
+ const CXXScopeSpec *SS, NamedDecl *FoundD,
+ const TemplateArgumentListInfo *TemplateArgs) {
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
@@ -1578,12 +1579,24 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
(CurContext != D->getDeclContext() &&
D->getDeclContext()->isFunctionOrMethod());
- DeclRefExpr *E = DeclRefExpr::Create(Context,
- SS ? SS->getWithLocInContext(Context)
- : NestedNameSpecifierLoc(),
- SourceLocation(),
- D, refersToEnclosingScope,
- NameInfo, Ty, VK, FoundD);
+ DeclRefExpr *E;
+ if (isa<VarTemplateSpecializationDecl>(D)) {
+ VarTemplateSpecializationDecl *VarSpec =
+ cast<VarTemplateSpecializationDecl>(D);
+
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ VarSpec->getTemplateKeywordLoc(), D, refersToEnclosingScope,
+ NameInfo.getLoc(), Ty, VK, FoundD, TemplateArgs);
+ } else {
+ assert(!TemplateArgs && "No template arguments for non-variable"
+ " template specialization referrences");
+ E = DeclRefExpr::Create(
+ Context,
+ SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(),
+ SourceLocation(), D, refersToEnclosingScope, NameInfo, Ty, VK, FoundD);
+ }
MarkDeclRefReferenced(E);
@@ -1870,7 +1883,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
bool IsInlineAsmIdentifier) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
-
if (SS.isInvalid())
return ExprError();
@@ -1961,6 +1973,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
+
// Otherwise, this could be an implicitly declared function reference (legal
// in C90, extension in C99, forbidden in C++).
if (HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
@@ -2056,8 +2069,19 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
R, TemplateArgs);
}
- if (TemplateArgs || TemplateKWLoc.isValid())
+ if (TemplateArgs || TemplateKWLoc.isValid()) {
+
+ // In C++1y, if this is a variable template id, then check it
+ // in BuildTemplateIdExpr().
+ // The single lookup result must be a variable template declaration.
+ if (Id.getKind() == UnqualifiedId::IK_TemplateId && Id.TemplateId &&
+ Id.TemplateId->Kind == TNK_Var_template) {
+ assert(R.getAsSingle<VarTemplateDecl>() &&
+ "There should only be one declaration found.");
+ }
+
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
+ }
return BuildDeclarationNameExpr(SS, R, ADL);
}
@@ -2524,10 +2548,9 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
/// \brief Complete semantic analysis for a reference to the given declaration.
-ExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- NamedDecl *D, NamedDecl *FoundD) {
+ExprResult Sema::BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
@@ -2539,8 +2562,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
- Diag(Loc, diag::err_template_decl_ref)
- << Template << SS.getRange();
+ Diag(Loc, diag::err_template_decl_ref) << (isa<VarTemplateDecl>(D) ? 1 : 0)
+ << Template << SS.getRange();
Diag(Template->getLocation(), diag::note_template_decl_here);
return ExprError();
}
@@ -2630,6 +2653,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
}
case Decl::Var:
+ case Decl::VarTemplateSpecialization:
+ case Decl::VarTemplatePartialSpecialization:
// In C, "extern void blah;" is valid and is an r-value.
if (!getLangOpts().CPlusPlus &&
!type.hasQualifiers() &&
@@ -2727,7 +2752,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
break;
}
- return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD);
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
+ TemplateArgs);
}
}
@@ -11690,28 +11716,64 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
if (!IsPotentiallyEvaluatedContext(SemaRef))
return;
- // Implicit instantiation of static data members of class templates.
- if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) {
+ VarTemplateSpecializationDecl *VarSpec =
+ dyn_cast<VarTemplateSpecializationDecl>(Var);
+
+ // Implicit instantiation of static data members, static data member
+ // templates of class templates, and variable template specializations.
+ // Delay instantiations of variable templates, except for those
+ // that could be used in a constant expression.
+ if (VarSpec || (Var->isStaticDataMember() &&
+ Var->getInstantiatedFromStaticDataMember())) {
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
- if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
- (!AlreadyInstantiated ||
- Var->isUsableInConstantExpressions(SemaRef.Context))) {
- if (!AlreadyInstantiated) {
- // This is a modification of an existing AST node. Notify listeners.
- if (ASTMutationListener *L = SemaRef.getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- MSInfo->setPointOfInstantiation(Loc);
+ if (VarSpec)
+ assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
+ "Can't instantiate a partial template specialization.");
+ if (Var->isStaticDataMember())
+ assert(MSInfo && "Missing member specialization information?");
+
+ SourceLocation PointOfInstantiation;
+ bool InstantiationIsOkay = true;
+ if (MSInfo) {
+ bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
+ TemplateSpecializationKind TSK = MSInfo->getTemplateSpecializationKind();
+
+ if (TSK == TSK_ImplicitInstantiation &&
+ (!AlreadyInstantiated ||
+ Var->isUsableInConstantExpressions(SemaRef.Context))) {
+ if (!AlreadyInstantiated) {
+ // This is a modification of an existing AST node. Notify listeners.
+ if (ASTMutationListener *L = SemaRef.getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
+ MSInfo->setPointOfInstantiation(Loc);
+ }
+ PointOfInstantiation = MSInfo->getPointOfInstantiation();
+ } else
+ InstantiationIsOkay = false;
+ } else {
+ if (VarSpec->getPointOfInstantiation().isInvalid())
+ VarSpec->setPointOfInstantiation(Loc);
+ PointOfInstantiation = VarSpec->getPointOfInstantiation();
+ }
+
+ if (InstantiationIsOkay) {
+ bool InstantiationDependent = false;
+ bool IsNonDependent =
+ VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
+ VarSpec->getTemplateArgsInfo(), InstantiationDependent)
+ : true;
+
+ // Do not instantiate specializations that are still type-dependent.
+ if (IsNonDependent) {
+ if (Var->isUsableInConstantExpressions(SemaRef.Context)) {
+ // Do not defer instantiations of variables which could be used in a
+ // constant expression.
+ SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
+ } else {
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
+ }
}
- SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation();
- if (Var->isUsableInConstantExpressions(SemaRef.Context))
- // Do not defer instantiations of variables which could be used in a
- // constant expression.
- SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var);
- else
- SemaRef.PendingInstantiations.push_back(
- std::make_pair(Var, PointOfInstantiation));
}
}
OpenPOWER on IntegriCloud