summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2016-09-13 21:08:20 +0000
committerHans Wennborg <hans@hanshq.net>2016-09-13 21:08:20 +0000
commit93f7547260f1e490fd95b68f05f0b69d356ce8be (patch)
treecba5529b87ce1a1cc6f25123ce8627eb8d9871c7
parent1e2e8eae5d0c5fd4fc12477c1137d13502f7da5a (diff)
downloadbcm5719-llvm-93f7547260f1e490fd95b68f05f0b69d356ce8be.tar.gz
bcm5719-llvm-93f7547260f1e490fd95b68f05f0b69d356ce8be.zip
Try harder to not inline dllimport functions referencing non-dllimport functions
In r246338, code was added to check for this, but it failed to take into account implicit destructor invocations because those are not reflected in the AST. This adds a separate check for them. llvm-svn: 281395
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp25
-rw-r--r--clang/test/CodeGenCXX/dllimport-members.cpp2
-rw-r--r--clang/test/CodeGenCXX/dllimport.cpp7
3 files changed, 31 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 1b6f5c376d8..085482b652a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1740,8 +1740,17 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
return Walker.Result;
}
-bool
-CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
+// Check if T is a class type with a destructor that's not dllimport.
+static bool HasNonDllImportDtor(QualType T) {
+ if (const RecordType *RT = dyn_cast<RecordType>(T))
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>())
+ return true;
+
+ return false;
+}
+
+bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
const auto *F = cast<FunctionDecl>(GD.getDecl());
@@ -1754,6 +1763,18 @@ CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
if (!Visitor.SafeToInline)
return false;
+
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(F)) {
+ // Implicit destructor invocations aren't captured in the AST, so the
+ // check above can't see them. Check for them manually here.
+ for (const Decl *Member : Dtor->getParent()->decls())
+ if (isa<FieldDecl>(Member))
+ if (HasNonDllImportDtor(cast<FieldDecl>(Member)->getType()))
+ return false;
+ for (const CXXBaseSpecifier &B : Dtor->getParent()->bases())
+ if (HasNonDllImportDtor(B.getType()))
+ return false;
+ }
}
// PR9614. Avoid cases where the source code is lying to us. An available
diff --git a/clang/test/CodeGenCXX/dllimport-members.cpp b/clang/test/CodeGenCXX/dllimport-members.cpp
index 1fed1bf0acf..19d9e1dfe7b 100644
--- a/clang/test/CodeGenCXX/dllimport-members.cpp
+++ b/clang/test/CodeGenCXX/dllimport-members.cpp
@@ -44,7 +44,7 @@ void useSpecials() {
}
// Used to force non-trivial special members.
-struct ForceNonTrivial {
+struct __declspec(dllimport) ForceNonTrivial {
ForceNonTrivial();
~ForceNonTrivial();
ForceNonTrivial(const ForceNonTrivial&);
diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp
index aff240f2876..1a24e34318a 100644
--- a/clang/test/CodeGenCXX/dllimport.cpp
+++ b/clang/test/CodeGenCXX/dllimport.cpp
@@ -347,6 +347,13 @@ __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nul
// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ"
USE(ReferencingImportedNew)
USE(ReferencingImportedDelete)
+struct ClassWithDtor { ~ClassWithDtor() {} };
+struct __declspec(dllimport) ClassWithNonDllImportField { ClassWithDtor t; };
+struct __declspec(dllimport) ClassWithNonDllImportBase : public ClassWithDtor { };
+USECLASS(ClassWithNonDllImportField);
+USECLASS(ClassWithNonDllImportBase);
+// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportBase@@QAE@XZ"(%struct.ClassWithNonDllImportBase*)
+// MO1-DAG: declare dllimport x86_thiscallcc void @"\01??1ClassWithNonDllImportField@@QAE@XZ"(%struct.ClassWithNonDllImportField*)
// A dllimport function with a TLS variable must not be available_externally.
__declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; }
OpenPOWER on IntegriCloud