]> granicus.if.org Git - clang/commitdiff
Switch the template specialization kind for a non-defining declaration of a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Jan 2017 02:56:07 +0000 (02:56 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Jan 2017 02:56:07 +0000 (02:56 +0000)
non-template function instantiated from a friend declaration in a class
template from TSK_ImplicitInstantiation to TSK_Undeclared.

It doesn't make sense for a non-template function to be flagged as being
instantiated from a template; that property really belongs to the entity
as a whole and not an individual declaration of it. There's some history
here:

 * r137934 started marking these functions as instantiations in order to
   work around an issue where we might instantiate a class template while
   we're still parsing its member definitions, and would otherwise fail
   to instantiate the friend definition

 * r177003 fixed the same issue but for friend templates, but did so by
   making the friends claim to be definitions even before we'd parsed
   their actual bodies; this made the r137934 change redundant

 * r293558 worked around a problem caused by the marking of a non-template
   function as a template instantiation in r137934

This change reverts the code changes from r293358 and r137934 and retains
all the tests.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293367 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiateDecl.cpp

index ed91057c4721dd3337f130ccb5144461869e3125..2310e99ab9d562ce539464bface4bea85c068e56 100644 (file)
@@ -1656,8 +1656,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
     FunctionTemplate->setLexicalDeclContext(LexicalDC);
 
     if (isFriend && D->isThisDeclarationADefinition()) {
-      // TODO: should we remember this connection regardless of whether
-      // the friend declaration provided a body?
       FunctionTemplate->setInstantiatedFromMemberTemplate(
                                            D->getDescribedFunctionTemplate());
     }
@@ -1668,13 +1666,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
                             TemplateArgumentList::CreateCopy(SemaRef.Context,
                                                              Innermost),
                                                 /*InsertPos=*/nullptr);
-  } else if (isFriend) {
-    // Note, we need this connection even if the friend doesn't have a body.
-    // Its body may exist but not have been attached yet due to deferred
-    // parsing.
-    // FIXME: It might be cleaner to set this when attaching the body to the
-    // friend function declaration, however that would require finding all the
-    // instantiations and modifying them.
+  } else if (isFriend && D->isThisDeclarationADefinition()) {
+    // Do not connect the friend to the template unless it's actually a
+    // definition. We don't want non-template functions to be marked as being
+    // template instantiations.
     Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
   }
 
@@ -3726,12 +3721,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
       PendingInstantiations.push_back(
         std::make_pair(Function, PointOfInstantiation));
     } else if (TSK == TSK_ImplicitInstantiation) {
-      if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
-          // A non-template function that is only lexically in a dependent
-          // context, such as a friend function in a class template, should
-          // not produce a warning.
-          (PatternDecl->getDescribedFunctionTemplate() ||
-           PatternDecl->getDeclContext()->isDependentContext())) {
+      if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
         Diag(PointOfInstantiation, diag::warn_func_template_missing)
           << Function;
         Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);