]> granicus.if.org Git - clang/commitdiff
[modules] Fix a rejects-valid resulting from emitting an inline function
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 13 Aug 2014 21:15:09 +0000 (21:15 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 13 Aug 2014 21:15:09 +0000 (21:15 +0000)
recursively within the emission of another inline function. This ultimately
led to us emitting the same inline function definition twice, which we then
rejected because we believed we had a mangled name conflict.

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

lib/CodeGen/ModuleBuilder.cpp
test/Modules/Inputs/cxx-irgen-top.h
test/Modules/cxx-irgen.cpp

index 7d75d8bff7b384642707983436c399b3fec5ed90..6c60b4e62c1883e7fb71fb37757dd4124481b7f6 100644 (file)
@@ -117,10 +117,14 @@ namespace {
     }
 
     void EmitDeferredDecls() {
+      if (DeferredInlineMethodDefinitions.empty())
+        return;
+
       // Emit any deferred inline method definitions. Note that more deferred
       // methods may be added during this loop, since ASTConsumer callbacks
       // can be invoked if AST inspection results in declarations being added.
-      for (unsigned I = 0; I < DeferredInlineMethodDefinitions.size(); ++I)
+      HandlingTopLevelDeclRAII HandlingDecl(*this);
+      for (unsigned I = 0; I != DeferredInlineMethodDefinitions.size(); ++I)
         Builder->EmitTopLevelDecl(DeferredInlineMethodDefinitions[I]);
       DeferredInlineMethodDefinitions.clear();
     }
index 43c0b18c775f947697086ae3dca4a49d925b9610..f1a0bee212503d7c44b22791748fbfa41365ff35 100644 (file)
@@ -38,3 +38,14 @@ namespace OperatorDeleteLookup {
   template<typename T> struct B { void operator delete(void*); virtual ~B() {} typedef int t; };
   typedef B<int>::t b_int_instantated;
 }
+
+namespace EmitInlineMethods {
+  struct A {
+    void f() {}
+    void g();
+  };
+  struct B {
+    void f();
+    void g() {}
+  };
+}
index 7bb128716221ea80d50dbb744f2643468ab9ac9b..4c6d81d203643aa33e1109081350db4911428389 100644 (file)
@@ -1,5 +1,6 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fmodules -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -g -o - %s | FileCheck %s
 // FIXME: When we have a syntax for modules in C++, use that.
 
 @import cxx_irgen_top;
@@ -10,6 +11,22 @@ CtorInit<int> x;
 @import cxx_irgen_left;
 @import cxx_irgen_right;
 
+// Keep these two namespace definitions separate; merging them hides the bug.
+namespace EmitInlineMethods {
+  // CHECK-DAG: define linkonce_odr void @_ZN17EmitInlineMethods1C1fEPNS_1AE(
+  // CHECK-DAG: declare void @_ZN17EmitInlineMethods1A1gEv(
+  struct C {
+    __attribute__((used)) void f(A *p) { p->g(); }
+  };
+}
+namespace EmitInlineMethods {
+  // CHECK-DAG: define linkonce_odr void @_ZN17EmitInlineMethods1D1fEPNS_1BE(
+  // CHECK-DAG: define linkonce_odr void @_ZN17EmitInlineMethods1B1gEv(
+  struct D {
+    __attribute__((used)) void f(B *p) { p->g(); }
+  };
+}
+
 // CHECK-DAG: define available_externally hidden {{signext i32|i32}} @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align
 int a = S<int>::g();