sberg created this revision.
sberg added a reviewer: cfe-commits.

...as that is apparently what MSVC does

http://reviews.llvm.org/D15267

Files:
  include/clang/AST/ASTConsumer.h
  include/clang/Frontend/MultiplexConsumer.h
  include/clang/Sema/Sema.h
  lib/CodeGen/CodeGenAction.cpp
  lib/CodeGen/ModuleBuilder.cpp
  lib/Frontend/MultiplexConsumer.cpp
  lib/Parse/ParseCXXInlineMethods.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeGenCXX/dllexport.cpp

Index: test/CodeGenCXX/dllexport.cpp
===================================================================
--- test/CodeGenCXX/dllexport.cpp
+++ test/CodeGenCXX/dllexport.cpp
@@ -255,9 +255,11 @@
 // GNU-DAG: define dllexport void @_Z7friend1v()
 // MSC-DAG: define dllexport void @"\01?friend2@@YAXXZ"()
 // GNU-DAG: define dllexport void @_Z7friend2v()
+// MSC-DAG: define weak_odr dllexport void @"\01?friend3@@YAXXZ"()
 struct FuncFriend {
   friend __declspec(dllexport) void friend1();
   friend __declspec(dllexport) void friend2();
+  friend __declspec(dllexport) void friend3() {}
 };
 __declspec(dllexport) void friend1() {}
                       void friend2() {}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10655,6 +10655,10 @@
   Consumer.HandleInlineMethodDefinition(D);
 }
 
+void Sema::ActOnFinishInlineFriendFunctionDef(FunctionDecl *D) {
+  Consumer.HandleInlineFriendFunctionDefinition(D);
+}
+
 static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, 
                              const FunctionDecl*& PossibleZeroParamPrototype) {
   // Don't warn about invalid declarations.
Index: lib/Parse/ParseCXXInlineMethods.cpp
===================================================================
--- lib/Parse/ParseCXXInlineMethods.cpp
+++ lib/Parse/ParseCXXInlineMethods.cpp
@@ -565,6 +565,8 @@
 
   if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D))
     Actions.ActOnFinishInlineMethodDef(MD);
+  else if (auto *FD = dyn_cast_or_null<FunctionDecl>(LM.D))
+    Actions.ActOnFinishInlineFriendFunctionDef(FD);
 }
 
 /// ParseLexedMemberInitializers - We finished parsing the member specification
Index: lib/Frontend/MultiplexConsumer.cpp
===================================================================
--- lib/Frontend/MultiplexConsumer.cpp
+++ lib/Frontend/MultiplexConsumer.cpp
@@ -271,6 +271,11 @@
     Consumer->HandleInlineMethodDefinition(D);
 }
 
+void MultiplexConsumer::HandleInlineFriendFunctionDefinition(FunctionDecl *D) {
+  for (auto &Consumer : Consumers)
+    Consumer->HandleInlineFriendFunctionDefinition(D);
+}
+
 void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
   for (auto &Consumer : Consumers)
     Consumer->HandleCXXStaticMemberVarInstantiation(VD);
Index: lib/CodeGen/ModuleBuilder.cpp
===================================================================
--- lib/CodeGen/ModuleBuilder.cpp
+++ lib/CodeGen/ModuleBuilder.cpp
@@ -163,6 +163,18 @@
         Builder->AddDeferredUnusedCoverageMapping(D);
     }
 
+    void HandleInlineFriendFunctionDefinition(FunctionDecl *D) override {
+      if (Diags.hasErrorOccurred())
+        return;
+
+      assert(D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend) &&
+             "Must be a friend decl");
+      assert(D->doesThisDeclarationHaveABody());
+
+      if (Ctx->getTargetInfo().getCXXABI().isMicrosoft())
+        Builder->EmitTopLevelDecl(D);
+    }
+
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
     /// to (e.g. struct, union, enum, class) is completed. This allows the
     /// client hack on the type, which can occur at any point in the file
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -132,6 +132,19 @@
         LLVMIRGeneration.stopTimer();
     }
 
+    void HandleInlineFriendFunctionDefinition(FunctionDecl *D) override {
+      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+                                     Context->getSourceManager(),
+                                     "LLVM IR generation of inline friend function");
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.startTimer();
+
+      Gen->HandleInlineFriendFunctionDefinition(D);
+
+      if (llvm::TimePassesIsEnabled)
+        LLVMIRGeneration.stopTimer();
+    }
+
     void HandleTranslationUnit(ASTContext &C) override {
       {
         PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1769,6 +1769,7 @@
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
   Decl *ActOnSkippedFunctionBody(Decl *Decl);
   void ActOnFinishInlineMethodDef(CXXMethodDecl *D);
+  void ActOnFinishInlineFriendFunctionDef(FunctionDecl *D);
 
   /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an
   /// attribute for which parsing is delayed.
Index: include/clang/Frontend/MultiplexConsumer.h
===================================================================
--- include/clang/Frontend/MultiplexConsumer.h
+++ include/clang/Frontend/MultiplexConsumer.h
@@ -37,6 +37,7 @@
   void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
   bool HandleTopLevelDecl(DeclGroupRef D) override;
   void HandleInlineMethodDefinition(CXXMethodDecl *D) override;
+  void HandleInlineFriendFunctionDefinition(FunctionDecl *D) override;
   void HandleInterestingDecl(DeclGroupRef D) override;
   void HandleTranslationUnit(ASTContext &Ctx) override;
   void HandleTagDeclDefinition(TagDecl *D) override;
Index: include/clang/AST/ASTConsumer.h
===================================================================
--- include/clang/AST/ASTConsumer.h
+++ include/clang/AST/ASTConsumer.h
@@ -59,6 +59,10 @@
   /// completed.
   virtual void HandleInlineMethodDefinition(CXXMethodDecl *D) {}
 
+  /// \brief This callback is invoked each time an inline friend function
+  /// definition is completed.
+  virtual void HandleInlineFriendFunctionDefinition(FunctionDecl *D) {}
+
   /// HandleInterestingDecl - Handle the specified interesting declaration. This
   /// is called by the AST reader when deserializing things that might interest
   /// the consumer. The default implementation forwards to HandleTopLevelDecl.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to