r184503 - Bug Fix: Template explicit instantiations should not have definitions (FixIts yet to be tested.)
Larisse Voufo
lvoufo at google.com
Thu Jun 20 17:08:47 PDT 2013
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}}
More information about the cfe-commits
mailing list