<div dir="ltr">Ok. I'll take a look.<div style>-- Larisse.</div><div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Jun 21, 2013 at 1:33 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, Jun 20, 2013 at 5:08 PM, Larisse Voufo <<a href="mailto:lvoufo@google.com">lvoufo@google.com</a>> wrote:<br>


> Author: lvoufo<br>
> Date: Thu Jun 20 19:08:46 2013<br>
> New Revision: 184503<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=184503&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=184503&view=rev</a><br>
> Log:<br>
> Bug Fix: Template explicit instantiations should not have definitions (FixIts yet to be tested.)<br>
><br>
> Added:<br>
>     cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp<br>
> Modified:<br>
>     cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
>     cfe/trunk/lib/Parse/ParseDecl.cpp<br>
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
>     cfe/trunk/lib/Parse/ParseTemplate.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=184503&r1=184502&r2=184503&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=184503&r1=184502&r2=184503&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Jun 20 19:08:46 2013<br>
> @@ -592,6 +592,9 @@ def err_explicit_instantiation_with_defi<br>
>      "explicit template instantiation cannot have a definition; if this "<br>
>      "definition is meant to be an explicit specialization, add '<>' after the "<br>
>      "'template' keyword">;<br>
> +def err_template_defn_explicit_instantiation : Error<<br>
> +  "%select{function|class}0 cannot be defined in an explicit instantiation; if this "<br>
> +  "declaration is meant to be a %select{function|class}0 definition, remove the 'template' keyword">;<br>
>  def err_explicit_instantiation_enum : Error<<br>
>      "enumerations cannot be explicitly instantiated">;<br>
>  def err_expected_template_parameter : Error<"expected template parameter">;<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=184503&r1=184502&r2=184503&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=184503&r1=184502&r2=184503&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jun 20 19:08:46 2013<br>
> @@ -13,6 +13,7 @@<br>
><br>
>  #include "clang/Parse/Parser.h"<br>
>  #include "RAIIObjectsForParser.h"<br>
> +#include "clang/AST/DeclTemplate.h"<br>
>  #include "clang/Basic/AddressSpaces.h"<br>
>  #include "clang/Basic/CharInfo.h"<br>
>  #include "clang/Basic/OpenCL.h"<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=184503&r1=184502&r2=184503&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=184503&r1=184502&r2=184503&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jun 20 19:08:46 2013<br>
> @@ -1539,6 +1539,14 @@ void Parser::ParseClassSpecifier(tok::To<br>
>    } else {<br>
<br>
</div></div>The previous case in the if/else if chain seems to do the wrong thing<br>
in the presence of explicit instantiations too. This code triggers an<br>
assert (with or without your patch):<br>
<br>
  template<typename T> struct A {};<br>
  struct B { template friend struct A<int> {}; };<br>
<br>
If you're not interested in fixing that, let me know and I'll file a bug.<br>
<div><div class="h5"><br>
>      if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)<br>
>        ProhibitAttributes(attrs);<br>
> +<br>
> +    if (TUK == Sema::TUK_Definition &&<br>
> +        TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {<br>
> +      // If the declarator-id is not a template-id, issue a diagnostic and<br>
> +      // recover by ignoring the 'template' keyword.<br>
> +      Diag(Tok, diag::err_template_defn_explicit_instantiation)<br>
> +        << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);<br>
> +    }<br>
><br>
>      bool IsDependent = false;<br>
><br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=184503&r1=184502&r2=184503&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=184503&r1=184502&r2=184503&view=diff</a><br>


> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Jun 20 19:08:46 2013<br>
> @@ -236,8 +236,39 @@ Parser::ParseSingleDeclarationAfterTempl<br>
>          << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());<br>
>        DS.ClearStorageClassSpecs();<br>
>      }<br>
> +<br>
> +    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {<br>
> +      if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {<br>
> +        // If the declarator-id is not a template-id, issue a diagnostic and<br>
> +        // recover by ignoring the 'template' keyword.<br>
> +        Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;<br>
<br>
</div></div>Please add<br>
<br>
  TemplateInfo = ParsedTemplateInfo();<br>
<br>
so that the downstream code sees a consistent state (this doesn't make<br>
any difference right now but should be more robust against future<br>
changes).<br>
<div class="im"><br>
> +      } else {<br>
> +        SourceLocation LAngleLoc<br>
> +          = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);<br>
> +        Diag(DeclaratorInfo.getIdentifierLoc(),<br>
> +             diag::err_explicit_instantiation_with_definition)<br>
> +          << SourceRange(TemplateInfo.TemplateLoc)<br>
> +          << FixItHint::CreateInsertion(LAngleLoc, "<>");<br>
> +<br>
> +        // Recover as if it were an explicit specialization.<br>
> +        TemplateParameterLists ParamLists;<br>
> +        SmallVector<Decl*, 4> TemplateParams;<br>
> +        ParamLists.push_back(<br>
> +            TemplateParameterList::Create(Actions.getASTContext(),<br>
> +                                          TemplateInfo.TemplateLoc,<br>
> +                                          LAngleLoc,<br>
> +                                          (NamedDecl**)TemplateParams.data(),<br>
> +                                          TemplateParams.size(), LAngleLoc));<br>
<br>
</div>You can use "0, 0," instead of TemplateParams.data() and<br>
TemplateParams.size() here, and remove the TemplateParams variable.<br>
<br>
Also, please use Actions.ActOnTemplateParameterList, rather than<br>
creating the template parameter list directly. We generally avoid<br>
directly manipulating the AST from the Parser.<br>
<div class="HOEnZb"><div class="h5"><br>
> +<br>
> +        return ParseFunctionDefinition(DeclaratorInfo,<br>
> +                                       ParsedTemplateInfo(&ParamLists,<br>
> +                                           /*isSpecialization=*/true,<br>
> +                                           /*LastParamListWasEmpty=*/true),<br>
> +                                       &LateParsedAttrs);<br>
> +      }<br>
> +    }<br>
>      return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,<br>
> -                                   &LateParsedAttrs);<br>
> +                                                          &LateParsedAttrs);<br>
>    }<br>
><br>
>    // Parse this declaration.<br>
><br>
> Added: cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp?rev=184503&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp?rev=184503&view=auto</a><br>


> ==============================================================================<br>
> --- cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp (added)<br>
> +++ cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp Thu Jun 20 19:08:46 2013<br>
> @@ -0,0 +1,52 @@<br>
> +// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
> +<br>
> +template<typename T> void f(T) { }<br>
> +template<typename T> void g(T) { }<br>
> +template<typename T> struct x { };<br>
> +template<typename T> struct y { };  // expected-note {{declared here}}<br>
> +<br>
> +namespace good {<br>
> +  template void f<int>(int);<br>
> +  template void g(int);<br>
> +  template struct x<int>;<br>
> +}<br>
> +<br>
> +namespace unsupported {<br>
> + template struct y;     // expected-error {{elaborated type refers to a template}}<br>
> +}<br>
> +<br>
> +template<typename T> void f0(T) { }<br>
> +template<typename T> void g0(T) { }<br>
> +template<typename T> struct x0 { }; // expected-note {{explicitly specialized declaration is here}}<br>
> +template<typename T> struct y0 { };<br>
> +<br>
> +// Should recover as if definition<br>
> +namespace noargs_body {<br>
> +  template void g0(int) { } // expected-error {{function cannot be defined in an explicit instantiation; if this declaration is meant to be a function definition, remove the 'template' keyword}}<br>
> +  template struct y0 { };   // expected-error {{class cannot be defined in an explicit instantiation; if this declaration is meant to be a class definition, remove the 'template' keyword}}<br>
> +}<br>
> +<br>
> +// Explicit specializations expected in global scope<br>
> +namespace exp_spec {<br>
> +  template<> void f0<int>(int) { }  // expected-error {{no function template matches function template specialization 'f0'}}<br>
> +  template<> struct x0<int> { };    // expected-error {{class template specialization of 'x0' must originally be declared in the global scope}}<br>
> +}<br>
> +<br>
> +template<typename T> void f1(T) { }<br>
> +template<typename T> struct x1 { };  // expected-note {{explicitly specialized declaration is here}}<br>
> +<br>
> +// Should recover as if specializations,<br>
> +// thus also complain about not being in global scope.<br>
> +namespace args_bad {<br>
> +  template void f1<int>(int) { }    // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \<br>


> +                                       expected-error {{no function template matches function template specialization 'f1'}}<br>
> +  template struct x1<int> { };      // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \<br>


> +                                       expected-error {{class template specialization of 'x1' must originally be declared in the global scope}}<br>
> +}<br>
> +<br>
> +template<typename T> void f2(T) { }<br>
> +template<typename T> struct x2 { };<br>
> +<br>
> +// Should recover as if specializations<br>
> +template void f2<int>(int) { }    // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}<br>


> +template struct x2<int> { };      // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}<br>


><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div>