diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 12 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 6 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp | 2 |
5 files changed, 36 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 48f58fb9a61..1773f4c56c6 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -283,7 +283,8 @@ def err_typename_refers_to_non_type_template : Error< 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">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 9cb4677f663..4c7aa27d514 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -603,14 +603,17 @@ private: : 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 @@ private: /// \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); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 72c9f33cd8d..65265afa919 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -617,21 +617,35 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } 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)) { diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 8e63fb89db3..64c5a08933a 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -101,6 +101,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // (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 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, 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); } diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp index b85b62f262c..a992648d7c4 100644 --- a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -6,7 +6,7 @@ namespace N { }; } -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 |