From: Larisse Voufo Date: Sat, 22 Jun 2013 13:56:11 +0000 (+0000) Subject: Instantiation bug fix extension (cf. r184503) -- minor code fixes, including a typo... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4985429d6f0dddbe168ec0ed4de029d56294e644;p=clang Instantiation bug fix extension (cf. r184503) -- minor code fixes, including a typo that caused a runtime assertion after firing diagnosis for class definitions, with the 'template' keyword as template header, in friend declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184634 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index d9370d4b9a..2567e413f2 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -595,6 +595,9 @@ def err_explicit_instantiation_with_definition : Error< 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_friend_explicit_instantiation : Error< + "friend cannot be declared in an explicit instantiation; if this " + "declaration is meant to be a friend declaration, remove the 'template' keyword">; def err_explicit_instantiation_enum : Error< "enumerations cannot be explicitly instantiated">; def err_expected_template_parameter : Error<"expected template parameter">; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 68d8e6ba4d..9ba1314171 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1465,7 +1465,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // This is an explicit specialization or a class template // partial specialization. TemplateParameterLists FakedParamLists; - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { // This looks like an explicit instantiation, because we have // something like @@ -1475,25 +1474,35 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // but it actually has a definition. Most likely, this was // meant to be an explicit specialization, but the user forgot // the '<>' after 'template'. - assert(TUK == Sema::TUK_Definition && "Expected a definition here"); - - SourceLocation LAngleLoc - = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); - Diag(TemplateId->TemplateNameLoc, - diag::err_explicit_instantiation_with_definition) - << SourceRange(TemplateInfo.TemplateLoc) - << FixItHint::CreateInsertion(LAngleLoc, "<>"); - - // Create a fake template parameter list that contains only - // "template<>", so that we treat this construct as a class - // template specialization. - FakedParamLists.push_back( - Actions.ActOnTemplateParameterList(0, SourceLocation(), - TemplateInfo.TemplateLoc, - LAngleLoc, - 0, 0, - LAngleLoc)); - TemplateParams = &FakedParamLists; + // It this is friend declaration however, since it cannot have a + // template header, it is most likely that the user meant to + // remove the 'template' keyword. + assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) && + "Expected a definition here"); + + if (TUK == Sema::TUK_Friend) { + Diag(DS.getFriendSpecLoc(), + diag::err_friend_explicit_instantiation); + TemplateParams = 0; + } else { + SourceLocation LAngleLoc + = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); + Diag(TemplateId->TemplateNameLoc, + diag::err_explicit_instantiation_with_definition) + << SourceRange(TemplateInfo.TemplateLoc) + << FixItHint::CreateInsertion(LAngleLoc, "<>"); + + // Create a fake template parameter list that contains only + // "template<>", so that we treat this construct as a class + // template specialization. + FakedParamLists.push_back( + Actions.ActOnTemplateParameterList(0, SourceLocation(), + TemplateInfo.TemplateLoc, + LAngleLoc, + 0, 0, + LAngleLoc)); + TemplateParams = &FakedParamLists; + } } // Build the class template specialization. @@ -1546,6 +1555,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // recover by ignoring the 'template' keyword. Diag(Tok, diag::err_template_defn_explicit_instantiation) << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); + TemplateParams = 0; } bool IsDependent = false; diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index e8e7efd19d..973eeb29d7 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -242,6 +242,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // 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; + return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(), + &LateParsedAttrs); } else { SourceLocation LAngleLoc = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); @@ -251,24 +253,21 @@ Parser::ParseSingleDeclarationAfterTemplate( << FixItHint::CreateInsertion(LAngleLoc, "<>"); // Recover as if it were an explicit specialization. - TemplateParameterLists ParamLists; - SmallVector TemplateParams; - ParamLists.push_back( - TemplateParameterList::Create(Actions.getASTContext(), - TemplateInfo.TemplateLoc, - LAngleLoc, - (NamedDecl**)TemplateParams.data(), - TemplateParams.size(), LAngleLoc)); + TemplateParameterLists FakedParamLists; + FakedParamLists.push_back( + Actions.ActOnTemplateParameterList(0, SourceLocation(), + TemplateInfo.TemplateLoc, + LAngleLoc, 0, 0, LAngleLoc)); return ParseFunctionDefinition(DeclaratorInfo, - ParsedTemplateInfo(&ParamLists, + ParsedTemplateInfo(&FakedParamLists, /*isSpecialization=*/true, /*LastParamListWasEmpty=*/true), &LateParsedAttrs); } } return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo, - &LateParsedAttrs); + &LateParsedAttrs); } // Parse this declaration.