<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>