summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/ModuleBuilder.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-06-06 17:36:17 +0000
committerHans Wennborg <hans@hanshq.net>2014-06-06 17:36:17 +0000
commitdfcb7d6a979c8c3ac5b1044e9bcd0f06e22123b3 (patch)
tree29bec582dd221a096c5a02470fe1d0fb39fa2880 /clang/lib/CodeGen/ModuleBuilder.cpp
parent9467be4f74a99a10924d2f3a66726351db698c71 (diff)
downloadbcm5719-llvm-dfcb7d6a979c8c3ac5b1044e9bcd0f06e22123b3.tar.gz
bcm5719-llvm-dfcb7d6a979c8c3ac5b1044e9bcd0f06e22123b3.zip
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 llvm-svn: 210356
Diffstat (limited to 'clang/lib/CodeGen/ModuleBuilder.cpp')
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp24
1 files changed, 18 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index e5bdae93fe7..c4a0e5c063d 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -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;
};
}
OpenPOWER on IntegriCloud