diff options
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 25 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport-members.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport.cpp | 7 |
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; } |