From: Richard Smith Date: Wed, 13 Aug 2014 21:15:09 +0000 (+0000) Subject: [modules] Fix a rejects-valid resulting from emitting an inline function X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=679b2ef02d616d40f47fa6dc4d92039e3d5e01f6;p=clang [modules] Fix a rejects-valid resulting from emitting an inline function 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 --- diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 7d75d8bff7..6c60b4e62c 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -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(); } diff --git a/test/Modules/Inputs/cxx-irgen-top.h b/test/Modules/Inputs/cxx-irgen-top.h index 43c0b18c77..f1a0bee212 100644 --- a/test/Modules/Inputs/cxx-irgen-top.h +++ b/test/Modules/Inputs/cxx-irgen-top.h @@ -38,3 +38,14 @@ namespace OperatorDeleteLookup { template struct B { void operator delete(void*); virtual ~B() {} typedef int t; }; typedef B::t b_int_instantated; } + +namespace EmitInlineMethods { + struct A { + void f() {} + void g(); + }; + struct B { + void f(); + void g() {} + }; +} diff --git a/test/Modules/cxx-irgen.cpp b/test/Modules/cxx-irgen.cpp index 7bb1287162..4c6d81d203 100644 --- a/test/Modules/cxx-irgen.cpp +++ b/test/Modules/cxx-irgen.cpp @@ -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 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::g();