[cfe-commits] r85620 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp test/CXX/temp/temp.spec/temp.explicit/p5.cpp
Douglas Gregor
dgregor at apple.com
Fri Oct 30 15:09:44 PDT 2009
Author: dgregor
Date: Fri Oct 30 17:09:44 2009
New Revision: 85620
URL: http://llvm.org/viewvc/llvm-project?rev=85620&view=rev
Log:
Improved fix for PR3844, which recovers better for class template
partial specializations and explicit instantiations of non-templates.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=85620&r1=85619&r2=85620&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Oct 30 17:09:44 2009
@@ -283,7 +283,8 @@
def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
def err_explicit_spec_non_template : Error<
- "explicit specialization of non-template %select{class|struct|union}0 %1">;
+ "explicit %select{specialization|instantiation}0 of non-template "
+ "%select{class|struct|union}1 %2">;
def err_variadic_templates : Error<
"variadic templates are only allowed in C++0x">;
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=85620&r1=85619&r2=85620&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Oct 30 17:09:44 2009
@@ -603,14 +603,17 @@
: Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
- bool isSpecialization)
+ bool isSpecialization,
+ bool lastParameterListWasEmpty = false)
: Kind(isSpecialization? ExplicitSpecialization : Template),
- TemplateParams(TemplateParams) { }
+ TemplateParams(TemplateParams),
+ LastParameterListWasEmpty(lastParameterListWasEmpty) { }
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
SourceLocation TemplateLoc)
: Kind(ExplicitInstantiation), TemplateParams(0),
- ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
+ ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
+ LastParameterListWasEmpty(false){ }
/// \brief The kind of template we are parsing.
enum {
@@ -635,6 +638,9 @@
/// \brief The location of the 'template' keyword, for an explicit
/// instantiation.
SourceLocation TemplateLoc;
+
+ /// \brief Whether the last template parameter list was empty.
+ bool LastParameterListWasEmpty;
};
void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=85620&r1=85619&r2=85620&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Oct 30 17:09:44 2009
@@ -617,21 +617,35 @@
}
Diag(NameLoc, diag::err_explicit_spec_non_template)
+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
<< (TagType == DeclSpec::TST_class? 0
: TagType == DeclSpec::TST_struct? 1
: 2)
<< Name
<< SourceRange(LAngleLoc, RAngleLoc);
- // If this is an explicit specialization, strip off the last template
- // parameter list, since we've removed its template arguments.
- if (TemplateParams && TemplateParams->size() > 1) {
- TemplateParams->pop_back();
- } else {
+ // Strip off the last template parameter list if it was empty, since
+ // we've removed its template argument list.
+ if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
+ if (TemplateParams && TemplateParams->size() > 1) {
+ TemplateParams->pop_back();
+ } else {
+ TemplateParams = 0;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
+ = ParsedTemplateInfo::NonTemplate;
+ }
+ } else if (TemplateInfo.Kind
+ == ParsedTemplateInfo::ExplicitInstantiation) {
+ // Pretend this is just a forward declaration.
TemplateParams = 0;
const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
= ParsedTemplateInfo::NonTemplate;
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
+ = SourceLocation();
+ const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
+ = SourceLocation();
}
+
}
} else if (Tok.is(tok::annot_template_id)) {
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=85620&r1=85619&r2=85620&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri Oct 30 17:09:44 2009
@@ -101,6 +101,7 @@
// (and retrieves the outer template parameter list from its
// context).
bool isSpecialization = true;
+ bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
TemplateParameterDepthCounter Depth(TemplateParameterDepth);
do {
@@ -140,13 +141,16 @@
if (!TemplateParams.empty()) {
isSpecialization = false;
++Depth;
+ } else {
+ LastParamListWasEmpty = true;
}
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
// Parse the actual template declaration.
return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(&ParamLists,
- isSpecialization),
+ isSpecialization,
+ LastParamListWasEmpty),
DeclEnd, AS);
}
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp?rev=85620&r1=85619&r2=85620&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp Fri Oct 30 17:09:44 2009
@@ -6,7 +6,7 @@
};
}
-template class Z<int>; // expected-error{{non-template class 'Z'}}
+template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}
// FIXME: This example from the standard is wrong; note posted to CWG reflector
// on 10/27/2009
More information about the cfe-commits
mailing list