Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -301,6 +301,8 @@ DeferredDeclsToEmit.push_back(DeferredGlobal(GV, GD)); } + std::vector DeferredTopLevelDeclsToEmit; + /// List of alias we have emitted. Used to make sure that what they point to /// is defined once we get to the end of the of the translation unit. std::vector Aliases; @@ -792,6 +794,11 @@ /// Emit code for a single top level declaration. void EmitTopLevelDecl(Decl *D); + /// Add a top level decl to be emitted at the end of codegen. + void AddDeferredTopLevelDeclToEmit(Decl* D) { + DeferredTopLevelDeclsToEmit.push_back(D); + } + /// Tell the consumer that this variable has been instantiated. void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); @@ -1006,6 +1013,8 @@ /// are emitted lazily. void EmitGlobal(GlobalDecl D); + void AddDeferredFunctionDefinition(FunctionDecl *D); + private: llvm::GlobalValue *GetGlobalValue(StringRef Ref); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -312,6 +312,7 @@ void CodeGenModule::clear() { DeferredDeclsToEmit.clear(); + DeferredTopLevelDeclsToEmit.clear(); } void CodeGenModule::Release() { @@ -1017,10 +1018,12 @@ } void CodeGenModule::EmitDeferred() { + for (Decl *D : DeferredTopLevelDeclsToEmit) + EmitTopLevelDecl(D); + // Emit code for any potentially referenced deferred decls. Since a // previously unused static decl may become used during the generation of code // for a static function, iterate until no changes are made. - while (true) { if (!DeferredVTables.empty()) { EmitDeferredVTables(); Index: lib/CodeGen/ModuleBuilder.cpp =================================================================== --- lib/CodeGen/ModuleBuilder.cpp +++ lib/CodeGen/ModuleBuilder.cpp @@ -91,7 +91,10 @@ if (!D->isDependentContext() && (D->hasAttr() || D->hasAttr() || D->hasAttr())) { - Builder->EmitTopLevelDecl(D); + // Defer emission to make sure that all other members, members of nested + // classes, etc. have been parsed before doing codegen for this method, + // in case it references any of them. + Builder->AddDeferredTopLevelDeclToEmit(D); } } Index: test/CodeGenCXX/attr-used.cpp =================================================================== --- test/CodeGenCXX/attr-used.cpp +++ test/CodeGenCXX/attr-used.cpp @@ -15,3 +15,13 @@ void __attribute__((used)) f() {} }; }; + +struct X2 { + // We must delay emission of bar() until foo() has had its body parsed, + // othersie foo() would not be emitted. + void __attribute__((used)) bar() { foo(); } + void foo() { } + + // CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv + // CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv +}; Index: test/CodeGenCXX/dllexport-members.cpp =================================================================== --- test/CodeGenCXX/dllexport-members.cpp +++ test/CodeGenCXX/dllexport-members.cpp @@ -40,10 +40,12 @@ // 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@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@ExportMembers@@UAEXXZ"(%struct.ExportMembers* %this) // M64-DAG: define dllexport void @"\01?virtualDef@ExportMembers@@UEAAXXZ"(%struct.ExportMembers* %this) Index: test/CodeGenCXX/dllexport.cpp =================================================================== --- test/CodeGenCXX/dllexport.cpp +++ test/CodeGenCXX/dllexport.cpp @@ -538,3 +538,17 @@ ~DefaultedCtorsDtors() = default; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE@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@S@ReferencedInlineMethodInNestedClass@@QAEXXZ" + // M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?bar@T@S@ReferencedInlineMethodInNestedClass@@QAEXXZ" +}