summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-03-30 06:27:31 +0000
committerStephan Bergmann <sbergman@redhat.com>2016-03-30 06:27:31 +0000
commit8d88a9262fa0065d980f1c25893d6a4bae6be665 (patch)
tree35c2c8fde3e994d88802f5cba851a9e18e68a724 /lib
parent7c065afc52d232e39013584be0bd972497b1c65e (diff)
For MS ABI, emit dllexport friend functions defined inline in class
...as that is apparently what MSVC does. This is an updated version of r263738, which had to be reverted in r263740 due to test failures. The original version had erroneously emitted functions that are defined in class templates, too (see the updated "Handle friend functions" code in EmitDeferredDecls, lib/CodeGen/ModuleBuilder.cpp). (The updated tests needed to be split out into their own dllexport-ms-friend.cpp because of the CHECK-NOTs which would have interfered with subsequent CHECK-DAGs in dllexport.cpp.) Differential Revision: http://reviews.llvm.org/D18430 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@264841 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CodeGenAction.cpp6
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp19
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp4
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp6
-rw-r--r--lib/Sema/SemaDecl.cpp4
5 files changed, 26 insertions, 13 deletions
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 638f79a245..edd258d3d5 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -123,14 +123,14 @@ namespace clang {
return true;
}
- void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ void HandleInlineFunctionDefinition(FunctionDecl *D) override {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
- "LLVM IR generation of inline method");
+ "LLVM IR generation of inline function");
if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.startTimer();
- Gen->HandleInlineMethodDefinition(D);
+ Gen->HandleInlineFunctionDefinition(D);
if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.stopTimer();
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index bd59332a27..5b7201e12d 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -143,12 +143,23 @@ namespace {
DeferredInlineMethodDefinitions.clear();
}
- void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ void HandleInlineFunctionDefinition(FunctionDecl *D) override {
if (Diags.hasErrorOccurred())
return;
assert(D->doesThisDeclarationHaveABody());
+ // Handle friend functions.
+ if (D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)) {
+ if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()
+ && !D->getLexicalDeclContext()->isDependentContext())
+ Builder->EmitTopLevelDecl(D);
+ return;
+ }
+
+ // Otherwise, must be a method.
+ auto MD = cast<CXXMethodDecl>(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,
@@ -157,13 +168,13 @@ namespace {
// void bar();
// void foo() { bar(); }
// } A;
- DeferredInlineMethodDefinitions.push_back(D);
+ DeferredInlineMethodDefinitions.push_back(MD);
// Provide some coverage mapping even for methods that aren't emitted.
// Don't do this for templated classes though, as they may not be
// instantiable.
- if (!D->getParent()->getDescribedClassTemplate())
- Builder->AddDeferredUnusedCoverageMapping(D);
+ if (!MD->getParent()->getDescribedClassTemplate())
+ Builder->AddDeferredUnusedCoverageMapping(MD);
}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 31c9b5f23f..ccda8c360a 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -272,9 +272,9 @@ bool MultiplexConsumer::HandleTopLevelDecl(DeclGroupRef D) {
return Continue;
}
-void MultiplexConsumer::HandleInlineMethodDefinition(CXXMethodDecl *D) {
+void MultiplexConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) {
for (auto &Consumer : Consumers)
- Consumer->HandleInlineMethodDefinition(D);
+ Consumer->HandleInlineFunctionDefinition(D);
}
void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 07e32b7e42..3db75c7ee7 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -564,8 +564,10 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
ConsumeAnyToken();
- if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D))
- Actions.ActOnFinishInlineMethodDef(MD);
+ if (auto *FD = dyn_cast_or_null<FunctionDecl>(LM.D))
+ if (isa<CXXMethodDecl>(FD) ||
+ FD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend))
+ Actions.ActOnFinishInlineFunctionDef(FD);
}
/// ParseLexedMemberInitializers - We finished parsing the member specification
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1f03735ef9..66abb655bb 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -10875,8 +10875,8 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
}
-void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
- Consumer.HandleInlineMethodDefinition(D);
+void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) {
+ Consumer.HandleInlineFunctionDefinition(D);
}
static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,