r210356 - Defer codegen of inline method definitions to the end of current top level declaration

Hans Wennborg hans at hanshq.net
Fri Jun 6 10:36:17 PDT 2014


Author: hans
Date: Fri Jun  6 12:36:17 2014
New Revision: 210356

URL: http://llvm.org/viewvc/llvm-project?rev=210356&view=rev
Log:
Defer codegen of inline method definitions to the end of current top level declaration

We would previously fail to emit a definition of bar() for the following code:

  struct __declspec(dllexport) S {
    void foo() {
      t->bar();
    }
    struct T {
      void bar() {}
    };
    T *t;
  };

Note that foo() is an exported method, but bar() is not. However, foo() refers
to bar() so we need to emit its definition. We would previously fail to
realise that bar() is used.

By deferring the method definitions until the end of the top level declaration,
we can simply call EmitTopLevelDecl on them and rely on the usual mechanisms
to decide whether the method should be emitted or not.

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

Modified:
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
    cfe/trunk/test/CodeGenCXX/attr-used.cpp
    cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
    cfe/trunk/test/CodeGenCXX/dllexport.cpp

Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=210356&r1=210355&r2=210356&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Fri Jun  6 12:36:17 2014
@@ -93,6 +93,12 @@ namespace {
       // Make sure to emit all elements of a Decl.
       for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
         Builder->EmitTopLevelDecl(*I);
+
+      // Emit any deferred inline method definitions.
+      for (CXXMethodDecl *MD : DeferredInlineMethodDefinitions)
+        Builder->EmitTopLevelDecl(MD);
+      DeferredInlineMethodDefinitions.clear();
+
       return true;
     }
 
@@ -102,12 +108,15 @@ namespace {
 
       assert(D->doesThisDeclarationHaveABody());
 
-      // We may have member functions that need to be emitted at this point.
-      if (!D->isDependentContext() &&
-          (D->hasAttr<UsedAttr>() || D->hasAttr<ConstructorAttr>() ||
-           D->hasAttr<DLLExportAttr>())) {
-        Builder->EmitTopLevelDecl(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,
+      // e.g.
+      //   typedef struct {
+      //     void bar();
+      //     void foo() { bar(); }
+      //   } A;
+      DeferredInlineMethodDefinitions.push_back(D);
     }
 
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
@@ -168,6 +177,9 @@ namespace {
     void HandleDependentLibrary(llvm::StringRef Lib) override {
       Builder->AddDependentLib(Lib);
     }
+
+  private:
+    std::vector<CXXMethodDecl *> DeferredInlineMethodDefinitions;
   };
 }
 

Modified: cfe/trunk/test/CodeGenCXX/attr-used.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-used.cpp?rev=210356&r1=210355&r2=210356&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-used.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-used.cpp Fri Jun  6 12:36:17 2014
@@ -15,3 +15,13 @@ struct X1 {
     void __attribute__((used)) f() {}
   };
 };
+
+struct X2 {
+  // We must delay emission of bar() until foo() has had its body parsed,
+  // otherwise foo() would not be emitted.
+  void __attribute__((used)) bar() { foo(); }
+  void foo() { }
+
+  // CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv
+  // CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv
+};

Modified: cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport-members.cpp?rev=210356&r1=210355&r2=210356&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport-members.cpp Fri Jun  6 12:36:17 2014
@@ -40,10 +40,12 @@ struct ExportMembers {
   // G64-DAG: define weak_odr dllexport                void @_ZN13ExportMembers15normalInlineDefEv(%struct.ExportMembers* %this)
   // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
   // G64-DAG: define weak_odr dllexport                void @_ZN13ExportMembers16normalInlineDeclEv(%struct.ExportMembers* %this)
+  // M32-DAG: define linkonce_odr       x86_thiscallcc void @"\01?referencedNonExportedInClass at ExportMembers@@QAEXXZ"
   __declspec(dllexport)                void normalDef();
-  __declspec(dllexport)                void normalInclass() {}
+  __declspec(dllexport)                void normalInclass() { referencedNonExportedInClass(); }
   __declspec(dllexport)                void normalInlineDef();
   __declspec(dllexport)         inline void normalInlineDecl();
+                                       void referencedNonExportedInClass() {}
 
   // M32-DAG: define          dllexport x86_thiscallcc void @"\01?virtualDef at ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this)
   // M64-DAG: define          dllexport                void @"\01?virtualDef at ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this)

Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=210356&r1=210355&r2=210356&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Fri Jun  6 12:36:17 2014
@@ -538,3 +538,17 @@ struct __declspec(dllexport) DefaultedCt
   ~DefaultedCtorsDtors() = default;
   // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE at XZ"
 };
+
+namespace ReferencedInlineMethodInNestedClass {
+  struct __declspec(dllexport) S {
+    void foo() {
+      t->bar();
+    }
+    struct T {
+      void bar() {}
+    };
+    T *t;
+  };
+  // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?foo at S@ReferencedInlineMethodInNestedClass@@QAEXXZ"
+  // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?bar at T@S at ReferencedInlineMethodInNestedClass@@QAEXXZ"
+}





More information about the cfe-commits mailing list