<p dir="ltr">On 20 Jul 2016 1:25 p.m., "Matthias Gehre" <<a href="mailto:M.Gehre@gmx.de">M.Gehre@gmx.de</a>> wrote:<br>
><br>
> mgehre created this revision.<br>
> mgehre added reviewers: klimek, aaron.ballman, rsmith.<br>
> mgehre added a subscriber: cfe-commits.<br>
><br>
> Look through expressions to determine if a nontype template argument has been given the value of the template parameter.<br>
><br>
> <a href="https://reviews.llvm.org/D22587">https://reviews.llvm.org/D22587</a><br>
><br>
> Files:<br>
> lib/AST/ASTContext.cpp<br>
> test/CXX/drs/dr2xx.cpp<br>
><br>
> Index: test/CXX/drs/dr2xx.cpp<br>
> ===================================================================<br>
> --- test/CXX/drs/dr2xx.cpp<br>
> +++ test/CXX/drs/dr2xx.cpp<br>
> @@ -275,9 +275,9 @@<br>
> static const int my_I = I;<br>
> static const int my_I2 = I+0;<br>
> static const int my_I3 = my_I;<br>
> - B<my_T1, T2, my_I>::type b3; // FIXME: expected-error {{missing 'typename'}}<br>
> + B<my_T1, T2, my_I>::type b3;<br>
> B<my_T1, T2, my_I2>::type b4; // expected-error {{missing 'typename'}}<br>
> - B<my_T1, T2, my_I3>::type b5; // FIXME: expected-error {{missing 'typename'}}<br>
> + B<my_T1, T2, my_I3>::type b5;<br>
> };<br>
> }<br>
><br>
> Index: lib/AST/ASTContext.cpp<br>
> ===================================================================<br>
> --- lib/AST/ASTContext.cpp<br>
> +++ lib/AST/ASTContext.cpp<br>
> @@ -4448,8 +4448,26 @@<br>
> case TemplateArgument::Null:<br>
> return Arg;<br>
><br>
> - case TemplateArgument::Expression:<br>
> + case TemplateArgument::Expression: {<br>
> + // Look through variable declarations that have been initialized to a non-type template<br>
> + // parameter, see 14.6.2.1 [temp.dep.type]:<br>
> + // [...], the argument must have been given the value of<br>
> + // the template parameter and not an expression involving the template parameter.<br>
> + auto *E = Arg.getAsExpr()->IgnoreImpCasts();</p>
<p dir="ltr">Are all implicit casts really OK here? If the parameter is narrowed, the value could change. Perhaps we should only walk through lvalue-to-rvalue conversions here. What about parentheses, should we skip those?</p>
<p dir="ltr">> + while(auto *DeclRef = dyn_cast_or_null<DeclRefExpr>(E)) {<br>
> + auto *D = DeclRef->getDecl();<br>
> + if (isa<NonTypeTemplateParmDecl>(D))<br>
> + return TemplateArgument(DeclRef);<br>
> +<br>
> + auto *VD = dyn_cast<VarDecl>(D);<br>
> + if (!VD)<br>
> + break;<br>
> + E = VD->getInit();<br>
> + if (E)<br>
> + E = E->IgnoreImpCasts();<br>
> + }<br>
> return Arg;<br>
> + }<br>
><br>
> case TemplateArgument::Declaration: {<br>
> ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());<br>
><br>
></p>