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