diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 134 |
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)); } } |