r184503 - Bug Fix: Template explicit instantiations should not have definitions (FixIts yet to be tested.)

Larisse Voufo lvoufo at google.com
Fri Jun 21 13:40:41 PDT 2013


Ok. I'll take a look.
-- Larisse.



On Fri, Jun 21, 2013 at 1:33 PM, Richard Smith <richard at metafoo.co.uk>wrote:

> On Thu, Jun 20, 2013 at 5:08 PM, Larisse Voufo <lvoufo at google.com> wrote:
> > Author: lvoufo
> > Date: Thu Jun 20 19:08:46 2013
> > New Revision: 184503
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=184503&view=rev
> > Log:
> > Bug Fix: Template explicit instantiations should not have definitions
> (FixIts yet to be tested.)
> >
> > Added:
> >     cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp
> > Modified:
> >     cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> >     cfe/trunk/lib/Parse/ParseDecl.cpp
> >     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> >     cfe/trunk/lib/Parse/ParseTemplate.cpp
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=184503&r1=184502&r2=184503&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Jun 20
> 19:08:46 2013
> > @@ -592,6 +592,9 @@ def err_explicit_instantiation_with_defi
> >      "explicit template instantiation cannot have a definition; if this "
> >      "definition is meant to be an explicit specialization, add '<>'
> after the "
> >      "'template' keyword">;
> > +def err_template_defn_explicit_instantiation : Error<
> > +  "%select{function|class}0 cannot be defined in an explicit
> instantiation; if this "
> > +  "declaration is meant to be a %select{function|class}0 definition,
> remove the 'template' keyword">;
> >  def err_explicit_instantiation_enum : Error<
> >      "enumerations cannot be explicitly instantiated">;
> >  def err_expected_template_parameter : Error<"expected template
> parameter">;
> >
> > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=184503&r1=184502&r2=184503&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jun 20 19:08:46 2013
> > @@ -13,6 +13,7 @@
> >
> >  #include "clang/Parse/Parser.h"
> >  #include "RAIIObjectsForParser.h"
> > +#include "clang/AST/DeclTemplate.h"
> >  #include "clang/Basic/AddressSpaces.h"
> >  #include "clang/Basic/CharInfo.h"
> >  #include "clang/Basic/OpenCL.h"
> >
> > Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=184503&r1=184502&r2=184503&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jun 20 19:08:46 2013
> > @@ -1539,6 +1539,14 @@ void Parser::ParseClassSpecifier(tok::To
> >    } else {
>
> The previous case in the if/else if chain seems to do the wrong thing
> in the presence of explicit instantiations too. This code triggers an
> assert (with or without your patch):
>
>   template<typename T> struct A {};
>   struct B { template friend struct A<int> {}; };
>
> If you're not interested in fixing that, let me know and I'll file a bug.
>
> >      if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
> >        ProhibitAttributes(attrs);
> > +
> > +    if (TUK == Sema::TUK_Definition &&
> > +        TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> {
> > +      // If the declarator-id is not a template-id, issue a diagnostic
> and
> > +      // recover by ignoring the 'template' keyword.
> > +      Diag(Tok, diag::err_template_defn_explicit_instantiation)
> > +        << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
> > +    }
> >
> >      bool IsDependent = false;
> >
> >
> > Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=184503&r1=184502&r2=184503&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Jun 20 19:08:46 2013
> > @@ -236,8 +236,39 @@ Parser::ParseSingleDeclarationAfterTempl
> >          << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
> >        DS.ClearStorageClassSpecs();
> >      }
> > +
> > +    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> {
> > +      if (DeclaratorInfo.getName().getKind() !=
> UnqualifiedId::IK_TemplateId) {
> > +        // If the declarator-id is not a template-id, issue a
> diagnostic and
> > +        // recover by ignoring the 'template' keyword.
> > +        Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
>
> Please add
>
>   TemplateInfo = ParsedTemplateInfo();
>
> so that the downstream code sees a consistent state (this doesn't make
> any difference right now but should be more robust against future
> changes).
>
> > +      } else {
> > +        SourceLocation LAngleLoc
> > +          = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
> > +        Diag(DeclaratorInfo.getIdentifierLoc(),
> > +             diag::err_explicit_instantiation_with_definition)
> > +          << SourceRange(TemplateInfo.TemplateLoc)
> > +          << FixItHint::CreateInsertion(LAngleLoc, "<>");
> > +
> > +        // Recover as if it were an explicit specialization.
> > +        TemplateParameterLists ParamLists;
> > +        SmallVector<Decl*, 4> TemplateParams;
> > +        ParamLists.push_back(
> > +            TemplateParameterList::Create(Actions.getASTContext(),
> > +                                          TemplateInfo.TemplateLoc,
> > +                                          LAngleLoc,
> > +
>  (NamedDecl**)TemplateParams.data(),
> > +                                          TemplateParams.size(),
> LAngleLoc));
>
> You can use "0, 0," instead of TemplateParams.data() and
> TemplateParams.size() here, and remove the TemplateParams variable.
>
> Also, please use Actions.ActOnTemplateParameterList, rather than
> creating the template parameter list directly. We generally avoid
> directly manipulating the AST from the Parser.
>
> > +
> > +        return ParseFunctionDefinition(DeclaratorInfo,
> > +                                       ParsedTemplateInfo(&ParamLists,
> > +                                           /*isSpecialization=*/true,
> > +
> /*LastParamListWasEmpty=*/true),
> > +                                       &LateParsedAttrs);
> > +      }
> > +    }
> >      return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
> > -                                   &LateParsedAttrs);
> > +
>  &LateParsedAttrs);
> >    }
> >
> >    // Parse this declaration.
> >
> > Added: cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp?rev=184503&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp (added)
> > +++ cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp Thu Jun 20 19:08:46
> 2013
> > @@ -0,0 +1,52 @@
> > +// RUN: %clang_cc1 -fsyntax-only -verify %s
> > +
> > +template<typename T> void f(T) { }
> > +template<typename T> void g(T) { }
> > +template<typename T> struct x { };
> > +template<typename T> struct y { };  // expected-note {{declared here}}
> > +
> > +namespace good {
> > +  template void f<int>(int);
> > +  template void g(int);
> > +  template struct x<int>;
> > +}
> > +
> > +namespace unsupported {
> > + template struct y;     // expected-error {{elaborated type refers to a
> template}}
> > +}
> > +
> > +template<typename T> void f0(T) { }
> > +template<typename T> void g0(T) { }
> > +template<typename T> struct x0 { }; // expected-note {{explicitly
> specialized declaration is here}}
> > +template<typename T> struct y0 { };
> > +
> > +// Should recover as if definition
> > +namespace noargs_body {
> > +  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}}
> > +  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}}
> > +}
> > +
> > +// Explicit specializations expected in global scope
> > +namespace exp_spec {
> > +  template<> void f0<int>(int) { }  // expected-error {{no function
> template matches function template specialization 'f0'}}
> > +  template<> struct x0<int> { };    // expected-error {{class template
> specialization of 'x0' must originally be declared in the global scope}}
> > +}
> > +
> > +template<typename T> void f1(T) { }
> > +template<typename T> struct x1 { };  // expected-note {{explicitly
> specialized declaration is here}}
> > +
> > +// Should recover as if specializations,
> > +// thus also complain about not being in global scope.
> > +namespace args_bad {
> > +  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}} \
> > +                                       expected-error {{no function
> template matches function template specialization 'f1'}}
> > +  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}} \
> > +                                       expected-error {{class template
> specialization of 'x1' must originally be declared in the global scope}}
> > +}
> > +
> > +template<typename T> void f2(T) { }
> > +template<typename T> struct x2 { };
> > +
> > +// Should recover as if specializations
> > +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}}
> > +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}}
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130621/9ab8994e/attachment.html>


More information about the cfe-commits mailing list