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 { 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; + } 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)); + + 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@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits