summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/ModuleBuilder.cpp
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-05-23 20:37:38 +0000
committerHans Wennborg <hans@hanshq.net>2014-05-23 20:37:38 +0000
commita926d84c4b8d96f434a519bbaf2f87303290e310 (patch)
tree75d3deae176d080523abe742a580d0faa81b0e61 /clang/lib/CodeGen/ModuleBuilder.cpp
parentd246759973b251eb160e5c9288d61ecae75b836e (diff)
downloadbcm5719-llvm-a926d84c4b8d96f434a519bbaf2f87303290e310.tar.gz
bcm5719-llvm-a926d84c4b8d96f434a519bbaf2f87303290e310.zip
Emit used/dllexport inline method definitions in nested classes (PR19743, PR11170)
The previous code that was supposed to handle this didn't work since parsing of inline method definitions is delayed to the end of the outer class definition. Thus, when HandleTagDeclDefinition() got called for the inner class, the inline functions in that class had not been parsed yet. Richard suggested that the way to do this is by handling inline method definitions through a new ASTConsumer callback. I really wanted to call ASTContext::DeclMustBeEmitted() instead of checking for attributes, but doing that causes us to compute linkage, and then we fail with "error: unsupported: typedef changes linkage of anonymous type, but linkage was already computed" on tests like this: (from SemaCXX/undefined-internal.cpp) :-/ namespace test7 { typedef struct { void bar(); void foo() { bar(); } } A; } Differential Revision: http://reviews.llvm.org/D3809 llvm-svn: 209549
Diffstat (limited to 'clang/lib/CodeGen/ModuleBuilder.cpp')
-rw-r--r--clang/lib/CodeGen/ModuleBuilder.cpp25
1 files changed, 14 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index 7873f44f1de..78cb82dc558 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -81,6 +81,20 @@ namespace {
return true;
}
+ void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ if (Diags.hasErrorOccurred())
+ return;
+
+ 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);
+ }
+ }
+
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// to (e.g. struct, union, enum, class) is completed. This allows the
/// client hack on the type, which can occur at any point in the file
@@ -90,17 +104,6 @@ namespace {
return;
Builder->UpdateCompletedType(D);
-
- // In C++, we may have member functions that need to be emitted at this
- // point.
- if (Ctx->getLangOpts().CPlusPlus && !D->isDependentContext()) {
- for (auto *M : D->decls())
- if (auto *Method = dyn_cast<CXXMethodDecl>(M))
- if (Method->doesThisDeclarationHaveABody() &&
- (Method->hasAttr<UsedAttr>() ||
- Method->hasAttr<ConstructorAttr>()))
- Builder->EmitTopLevelDecl(Method);
- }
}
void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
OpenPOWER on IntegriCloud