mgehre created this revision. mgehre added reviewers: klimek, aaron.ballman, rsmith. mgehre added a subscriber: cfe-commits.
Look through expressions to determine if a nontype template argument has been given the value of the template parameter. https://reviews.llvm.org/D22587 Files: lib/AST/ASTContext.cpp test/CXX/drs/dr2xx.cpp Index: test/CXX/drs/dr2xx.cpp =================================================================== --- test/CXX/drs/dr2xx.cpp +++ test/CXX/drs/dr2xx.cpp @@ -275,9 +275,9 @@ static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; - B<my_T1, T2, my_I>::type b3; // FIXME: expected-error {{missing 'typename'}} + B<my_T1, T2, my_I>::type b3; B<my_T1, T2, my_I2>::type b4; // expected-error {{missing 'typename'}} - B<my_T1, T2, my_I3>::type b5; // FIXME: expected-error {{missing 'typename'}} + B<my_T1, T2, my_I3>::type b5; }; } Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -4448,8 +4448,26 @@ case TemplateArgument::Null: return Arg; - case TemplateArgument::Expression: + case TemplateArgument::Expression: { + // Look through variable declarations that have been initialized to a non-type template + // parameter, see 14.6.2.1 [temp.dep.type]: + // [...], the argument must have been given the value of + // the template parameter and not an expression involving the template parameter. + auto *E = Arg.getAsExpr()->IgnoreImpCasts(); + while(auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) { + auto *D = DeclRef->getDecl(); + if (isa<NonTypeTemplateParmDecl>(D)) + return TemplateArgument(DeclRef); + + auto *VD = dyn_cast<VarDecl>(D); + if (!VD) + break; + E = VD->getInit(); + if (E) + E = E->IgnoreImpCasts(); + } return Arg; + } case TemplateArgument::Declaration: { ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
Index: test/CXX/drs/dr2xx.cpp =================================================================== --- test/CXX/drs/dr2xx.cpp +++ test/CXX/drs/dr2xx.cpp @@ -275,9 +275,9 @@ static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; - B<my_T1, T2, my_I>::type b3; // FIXME: expected-error {{missing 'typename'}} + B<my_T1, T2, my_I>::type b3; B<my_T1, T2, my_I2>::type b4; // expected-error {{missing 'typename'}} - B<my_T1, T2, my_I3>::type b5; // FIXME: expected-error {{missing 'typename'}} + B<my_T1, T2, my_I3>::type b5; }; } Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -4448,8 +4448,26 @@ case TemplateArgument::Null: return Arg; - case TemplateArgument::Expression: + case TemplateArgument::Expression: { + // Look through variable declarations that have been initialized to a non-type template + // parameter, see 14.6.2.1 [temp.dep.type]: + // [...], the argument must have been given the value of + // the template parameter and not an expression involving the template parameter. + auto *E = Arg.getAsExpr()->IgnoreImpCasts(); + while(auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) { + auto *D = DeclRef->getDecl(); + if (isa<NonTypeTemplateParmDecl>(D)) + return TemplateArgument(DeclRef); + + auto *VD = dyn_cast<VarDecl>(D); + if (!VD) + break; + E = VD->getInit(); + if (E) + E = E->IgnoreImpCasts(); + } return Arg; + } case TemplateArgument::Declaration: { ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits