r264841 - For MS ABI, emit dllexport friend functions defined inline in class

Stephan Bergmann via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 29 23:27:33 PDT 2016


Author: sberg
Date: Wed Mar 30 01:27:31 2016
New Revision: 264841

URL: http://llvm.org/viewvc/llvm-project?rev=264841&view=rev
Log:
For MS ABI, emit dllexport friend functions defined inline in class

...as that is apparently what MSVC does.  This is an updated version of r263738,
which had to be reverted in r263740 due to test failures.  The original version
had erroneously emitted functions that are defined in class templates, too (see
the updated "Handle friend functions" code in EmitDeferredDecls,
lib/CodeGen/ModuleBuilder.cpp).  (The updated tests needed to be split out into
their own dllexport-ms-friend.cpp because of the CHECK-NOTs which would have
interfered with subsequent CHECK-DAGs in dllexport.cpp.)

Differential Revision: http://reviews.llvm.org/D18430

Added:
    cfe/trunk/test/CodeGenCXX/dllexport-ms-friend.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTConsumer.h
    cfe/trunk/include/clang/Frontend/MultiplexConsumer.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/CodeGen/CodeGenAction.cpp
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
    cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/AST/ASTConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTConsumer.h?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTConsumer.h (original)
+++ cfe/trunk/include/clang/AST/ASTConsumer.h Wed Mar 30 01:27:31 2016
@@ -55,9 +55,9 @@ public:
   /// \returns true to continue parsing, or false to abort parsing.
   virtual bool HandleTopLevelDecl(DeclGroupRef D);
 
-  /// \brief This callback is invoked each time an inline method definition is
-  /// completed.
-  virtual void HandleInlineMethodDefinition(CXXMethodDecl *D) {}
+  /// \brief This callback is invoked each time an inline (method or friend)
+  /// function definition in a class is completed.
+  virtual void HandleInlineFunctionDefinition(FunctionDecl *D) {}
 
   /// HandleInterestingDecl - Handle the specified interesting declaration. This
   /// is called by the AST reader when deserializing things that might interest

Modified: cfe/trunk/include/clang/Frontend/MultiplexConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/MultiplexConsumer.h?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/MultiplexConsumer.h (original)
+++ cfe/trunk/include/clang/Frontend/MultiplexConsumer.h Wed Mar 30 01:27:31 2016
@@ -36,7 +36,7 @@ public:
   void Initialize(ASTContext &Context) override;
   void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
   bool HandleTopLevelDecl(DeclGroupRef D) override;
-  void HandleInlineMethodDefinition(CXXMethodDecl *D) override;
+  void HandleInlineFunctionDefinition(FunctionDecl *D) override;
   void HandleInterestingDecl(DeclGroupRef D) override;
   void HandleTranslationUnit(ASTContext &Ctx) override;
   void HandleTagDeclDefinition(TagDecl *D) override;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 30 01:27:31 2016
@@ -1773,7 +1773,7 @@ public:
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
   Decl *ActOnSkippedFunctionBody(Decl *Decl);
-  void ActOnFinishInlineMethodDef(CXXMethodDecl *D);
+  void ActOnFinishInlineFunctionDef(FunctionDecl *D);
 
   /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an
   /// attribute for which parsing is delayed.

Modified: cfe/trunk/lib/CodeGen/CodeGenAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenAction.cpp?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenAction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp Wed Mar 30 01:27:31 2016
@@ -123,14 +123,14 @@ namespace clang {
       return true;
     }
 
-    void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+    void HandleInlineFunctionDefinition(FunctionDecl *D) override {
       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                      Context->getSourceManager(),
-                                     "LLVM IR generation of inline method");
+                                     "LLVM IR generation of inline function");
       if (llvm::TimePassesIsEnabled)
         LLVMIRGeneration.startTimer();
 
-      Gen->HandleInlineMethodDefinition(D);
+      Gen->HandleInlineFunctionDefinition(D);
 
       if (llvm::TimePassesIsEnabled)
         LLVMIRGeneration.stopTimer();

Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Wed Mar 30 01:27:31 2016
@@ -143,12 +143,23 @@ namespace {
       DeferredInlineMethodDefinitions.clear();
     }
 
-    void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+    void HandleInlineFunctionDefinition(FunctionDecl *D) override {
       if (Diags.hasErrorOccurred())
         return;
 
       assert(D->doesThisDeclarationHaveABody());
 
+      // Handle friend functions.
+      if (D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)) {
+        if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()
+            && !D->getLexicalDeclContext()->isDependentContext())
+          Builder->EmitTopLevelDecl(D);
+        return;
+      }
+
+      // Otherwise, must be a method.
+      auto MD = cast<CXXMethodDecl>(D);
+
       // We may want to emit this definition. However, that decision might be
       // based on computing the linkage, and we have to defer that in case we
       // are inside of something that will change the method's final linkage,
@@ -157,13 +168,13 @@ namespace {
       //     void bar();
       //     void foo() { bar(); }
       //   } A;
-      DeferredInlineMethodDefinitions.push_back(D);
+      DeferredInlineMethodDefinitions.push_back(MD);
 
       // Provide some coverage mapping even for methods that aren't emitted.
       // Don't do this for templated classes though, as they may not be
       // instantiable.
-      if (!D->getParent()->getDescribedClassTemplate())
-        Builder->AddDeferredUnusedCoverageMapping(D);
+      if (!MD->getParent()->getDescribedClassTemplate())
+        Builder->AddDeferredUnusedCoverageMapping(MD);
     }
 
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl

Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original)
+++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Wed Mar 30 01:27:31 2016
@@ -272,9 +272,9 @@ bool MultiplexConsumer::HandleTopLevelDe
   return Continue;
 }
 
-void MultiplexConsumer::HandleInlineMethodDefinition(CXXMethodDecl *D) {
+void MultiplexConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
   for (auto &Consumer : Consumers)
-    Consumer->HandleInlineMethodDefinition(D);
+    Consumer->HandleInlineFunctionDefinition(D);
 }
 
 void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Wed Mar 30 01:27:31 2016
@@ -564,8 +564,10 @@ void Parser::ParseLexedMethodDef(LexedMe
   if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
     ConsumeAnyToken();
 
-  if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D))
-    Actions.ActOnFinishInlineMethodDef(MD);
+  if (auto *FD = dyn_cast_or_null<FunctionDecl>(LM.D))
+    if (isa<CXXMethodDecl>(FD) ||
+        FD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend))
+      Actions.ActOnFinishInlineFunctionDef(FD);
 }
 
 /// ParseLexedMemberInitializers - We finished parsing the member specification

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=264841&r1=264840&r2=264841&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 30 01:27:31 2016
@@ -10875,8 +10875,8 @@ Sema::ActOnStartOfFunctionDef(Scope *FnB
   return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
 }
 
-void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
-  Consumer.HandleInlineMethodDefinition(D);
+void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) {
+  Consumer.HandleInlineFunctionDefinition(D);
 }
 
 static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, 

Added: cfe/trunk/test/CodeGenCXX/dllexport-ms-friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport-ms-friend.cpp?rev=264841&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport-ms-friend.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/dllexport-ms-friend.cpp Wed Mar 30 01:27:31 2016
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple %ms_abi_triple -fms-extensions -emit-llvm -O0 -o - %s | FileCheck %s
+
+// Friend functions defined in classes are emitted.
+// CHECK: define weak_odr dllexport void @"\01?friend1@@YAXXZ"()
+struct FuncFriend1 {
+  friend __declspec(dllexport) void friend1() {}
+};
+
+// But function templates and functions defined in class templates are not
+// emitted.
+// CHECK-NOT: friend2
+// CHECK-NOT: friend3
+// CHECK-NOT: friend4
+struct FuncFriend2 {
+  template<typename> friend __declspec(dllexport) void friend2() {}
+};
+template<typename> struct FuncFriend3 {
+  friend __declspec(dllexport) void friend3() {}
+  struct Inner {
+    friend __declspec(dllexport) void friend4() {}
+  };
+};




More information about the cfe-commits mailing list