r304852 - Improve error recovery for missing 'template' keyword in contexts where the

Mikael Holmén via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 6 23:15:02 PDT 2017


Hi Richard,

See below.

On 06/07/2017 02:29 AM, Richard Smith via cfe-commits wrote:
> Author: rsmith
> Date: Tue Jun  6 19:29:44 2017
> New Revision: 304852
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=304852&view=rev
> Log:
> Improve error recovery for missing 'template' keyword in contexts where the
> template is valid with or without it (with different meanings).
> 
> If we see "dependent.x<...", and what follows the '<' is a valid expression,
> we must parse the '<' as a comparison rather than a template angle bracket.
> When we later come to instantiate, if we find that the LHS of the '<' actually
> names an overload set containing function templates, produce a diagnostic
> suggesting that the 'template' keyword was missed rather than producing a
> mysterious diagnostic saying that the function must be called (and pointing
> at what looks to already be a function call!).
> 
> Modified:
>      cfe/trunk/lib/Sema/SemaExpr.cpp
>      cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp
> 
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=304852&r1=304851&r2=304852&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun  6 19:29:44 2017
> @@ -11828,6 +11828,32 @@ ExprResult Sema::BuildBinOp(Scope *S, So
>             RHSExpr->getType()->isOverloadableType())
>           return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
>       }
> +
> +    // If we're instantiating "a.x < b" or "A::x < b" and 'x' names a function
> +    // template, diagnose the missing 'template' keyword instead of diagnosing
> +    // an invalid use of a bound member function.
> +    //
> +    // Note that "A::x < b" might be valid if 'b' has an overloadable type due
> +    // to C++1z [over.over]/1.4, but we already checked for that case above.
> +    if (Opc == BO_LT && inTemplateInstantiation() &&
> +        (pty->getKind() == BuiltinType::BoundMember ||
> +         pty->getKind() == BuiltinType::Overload)) {
> +      auto *OE = dyn_cast<OverloadExpr>(LHSExpr);
> +      if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() &&
> +          std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) {
> +            return isa<FunctionTemplateDecl>(ND);
> +          })) {
> +        if (auto *Q = OE->getQualifier()) {

I'm getting a compiler warning that looks reasonable here:

../tools/clang/lib/Sema/SemaExpr.cpp:11846:19: error: unused variable 
'Q' [-Werror,-Wunused-variable]
         if (auto *Q = OE->getQualifier()) {
                   ^
1 error generated.


I got the above with clang 3.6.

Regards,
Mikael

> +          Diag(OE->getQualifierLoc().getBeginLoc(),
> +               diag::err_template_kw_missing)
> +            << OE->getName().getAsString() << "";
> +        } else {
> +          Diag(OE->getNameLoc(), diag::err_template_kw_missing)
> +            << OE->getName().getAsString() << "";
> +        }
> +        return ExprError();
> +      }
> +    }
>           
>       ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
>       if (LHS.isInvalid()) return ExprError();
> 
> Modified: cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp?rev=304852&r1=304851&r2=304852&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp Tue Jun  6 19:29:44 2017
> @@ -17,6 +17,28 @@ struct X {
>     }
>   };
>   
> +struct MrsBadcrumble {
> +  friend MrsBadcrumble operator<(void (*)(int), MrsBadcrumble);
> +  friend void operator>(MrsBadcrumble, int);
> +} mb;
> +
> +template<int N, typename T> void f(T t) {
> +  t.f<N>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'f'}}
> +  t.T::f<N>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'f'}}
> +  T::g<N>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}}
> +
> +  // Note: no diagnostic here, this is actually valid as a comparison between
> +  // the decayed pointer to Y::g<> and mb!
> +  T::g<mb>(0);
> +}
> +
> +struct Y {
> +  template <int> void f(int);
> +  template <int = 0> static void g(int); // expected-warning 0-1{{extension}}
> +};
> +void q() { void (*p)(int) = Y::g; }
> +template void f<0>(Y); // expected-note {{in instantiation of}}
> +
>   namespace PR9401 {
>     // From GCC PR c++/45558
>     template <typename S, typename T>
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> 


More information about the cfe-commits mailing list