]> granicus.if.org Git - clang/commitdiff
Instantiation bug fix extension (cf. r184503) -- minor code fixes, including a typo...
authorLarisse Voufo <lvoufo@google.com>
Sat, 22 Jun 2013 13:56:11 +0000 (13:56 +0000)
committerLarisse Voufo <lvoufo@google.com>
Sat, 22 Jun 2013 13:56:11 +0000 (13:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184634 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseTemplate.cpp

index d9370d4b9a393bb750987a85f1514ddba22d2296..2567e413f25f5c9c88016ca8dcab5d6769fb3c1f 100644 (file)
@@ -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">;
index 68d8e6ba4d0fc1bbff6d155b5dd3802ec114eec9..9ba1314171229e27439be44d6d3feba3ea9ebac8 100644 (file)
@@ -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;
index e8e7efd19d6698bbbb021e776d7546908fbaa08c..973eeb29d7b3eeb64c3d9476203f8d94b60eb573 100644 (file)
@@ -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<Decl*, 4> 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.