sepavloff updated this revision to Diff 101517.
sepavloff added a comment.

Rebased patch

https://reviews.llvm.org/D30375

Files:
  include/clang/AST/Decl.h
  include/clang/Sema/Sema.h
  lib/Parse/Parser.cpp
  lib/Sema/SemaCUDA.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/SemaCXX/friend2.cpp

Index: test/SemaCXX/friend2.cpp
===================================================================
--- test/SemaCXX/friend2.cpp
+++ test/SemaCXX/friend2.cpp
@@ -170,3 +170,15 @@
 template class Test<int>;
 
 }
+
+namespace pr14785 {
+template<typename T>
+struct Somewhat {
+  void internal() const { }
+  friend void operator+(int const &, Somewhat<T> const &) {}  // expected-error{{redefinition of 'operator+'}}
+};
+
+void operator+(int const &, Somewhat<char> const &x) {  // expected-note {{previous definition is here}}
+  x.internal();  // expected-note{{in instantiation of template class 'pr14785::Somewhat<char>' requested here}}
+}
+}
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3894,6 +3894,7 @@
     SubstQualifier(*this, PatternDecl, Function, TemplateArgs);
 
     ActOnStartOfFunctionDef(nullptr, Function);
+    ActOnStartOfFunctionBody(Function);
 
     // Enter the scope of this instantiation. We don't use
     // PushDeclContext because we don't have a scope.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -12028,11 +12028,6 @@
       return D;
   }
 
-  // Mark this function as "will have a body eventually".  This lets users to
-  // call e.g. isInlineDefinitionExternallyVisible while we're still parsing
-  // this function.
-  FD->setWillHaveBody();
-
   // If we are instantiating a generic lambda call operator, push
   // a LambdaScopeInfo onto the function stack.  But use the information
   // that's already been calculated (ActOnLambdaExpr) to prime the current
@@ -12202,6 +12197,19 @@
   return Decl;
 }
 
+/// Semantic action called by parser when it expects that the current function
+/// definition will have a body statement.
+void Sema::ActOnStartOfFunctionBody(Decl *D) {
+  if (!D)
+    return;
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // Mark this function as "will have a body eventually".  This lets users to
+    // call e.g. isInlineDefinitionExternallyVisible while we're still parsing
+    // this function.
+    FD->setWillHaveBody();
+  }
+}
+
 Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
   return ActOnFinishFunctionBody(D, BodyArg, false);
 }
Index: lib/Sema/SemaCUDA.cpp
===================================================================
--- lib/Sema/SemaCUDA.cpp
+++ lib/Sema/SemaCUDA.cpp
@@ -629,12 +629,6 @@
   // emitted, because (say) the definition could include "inline".
   FunctionDecl *Def = FD->getDefinition();
 
-  // We may currently be parsing the body of FD, in which case
-  // FD->getDefinition() will be null, but we still want to treat FD as though
-  // it's a definition.
-  if (!Def && FD->willHaveBody())
-    Def = FD;
-
   if (Def &&
       !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def)))
     return true;
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -1186,6 +1186,8 @@
     return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
   }
 
+  Actions.ActOnStartOfFunctionBody(Res);
+
   if (Tok.is(tok::kw_try))
     return ParseFunctionTryBlock(Res, BodyScope);
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1981,6 +1981,7 @@
   bool canSkipFunctionBody(Decl *D);
 
   void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope);
+  void ActOnStartOfFunctionBody(Decl *Decl);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
   Decl *ActOnSkippedFunctionBody(Decl *Decl);
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1837,7 +1837,7 @@
   ///
   bool isThisDeclarationADefinition() const {
     return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
-      hasDefiningAttr();
+      WillHaveBody || hasDefiningAttr();
   }
 
   /// doesThisDeclarationHaveABody - Returns whether this specific
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to