Author: hans Date: Wed Feb 15 17:28:10 2017 New Revision: 295258 URL: http://llvm.org/viewvc/llvm-project?rev=295258&view=rev Log: [dllimport] Check for dtor references in functions
Destructor references are not modelled explicitly in the AST. This adds checks for destructor calls due to variable definitions and temporaries. If a dllimport function references a non-dllimport destructor, it must not be emitted available_externally, as the referenced destructor might live across the DLL boundary and isn't exported. Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/test/CodeGenCXX/dllimport.cpp Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=295258&r1=295257&r2=295258&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Feb 15 17:28:10 2017 @@ -1693,6 +1693,16 @@ void CodeGenModule::EmitGlobal(GlobalDec } } +// Check if T is a class type with a destructor that's not dllimport. +static bool HasNonDllImportDtor(QualType T) { + if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) + return true; + + return false; +} + namespace { struct FunctionIsDirectlyRecursive : public RecursiveASTVisitor<FunctionIsDirectlyRecursive> { @@ -1726,6 +1736,7 @@ namespace { } }; + // Make sure we're not referencing non-imported vars or functions. struct DLLImportFunctionVisitor : public RecursiveASTVisitor<DLLImportFunctionVisitor> { bool SafeToInline = true; @@ -1733,12 +1744,25 @@ namespace { bool shouldVisitImplicitCode() const { return true; } bool VisitVarDecl(VarDecl *VD) { - // A thread-local variable cannot be imported. - SafeToInline = !VD->getTLSKind(); + if (VD->getTLSKind()) { + // A thread-local variable cannot be imported. + SafeToInline = false; + return SafeToInline; + } + + // A variable definition might imply a destructor call. + if (VD->isThisDeclarationADefinition()) + SafeToInline = !HasNonDllImportDtor(VD->getType()); + + return SafeToInline; + } + + bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + if (const auto *D = E->getTemporary()->getDestructor()) + SafeToInline = D->hasAttr<DLLImportAttr>(); return SafeToInline; } - // Make sure we're not referencing non-imported vars or functions. bool VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *VD = E->getDecl(); if (isa<FunctionDecl>(VD)) @@ -1747,10 +1771,12 @@ namespace { SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>(); return SafeToInline; } + bool VisitCXXConstructExpr(CXXConstructExpr *E) { SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>(); return SafeToInline; } + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { CXXMethodDecl *M = E->getMethodDecl(); if (!M) { @@ -1761,10 +1787,12 @@ namespace { } return SafeToInline; } + bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>(); return SafeToInline; } + bool VisitCXXNewExpr(CXXNewExpr *E) { SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>(); return SafeToInline; @@ -1793,16 +1821,6 @@ CodeGenModule::isTriviallyRecursive(cons return Walker.Result; } -// Check if T is a class type with a destructor that's not dllimport. -static bool HasNonDllImportDtor(QualType T) { - if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) - 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; Modified: cfe/trunk/test/CodeGenCXX/dllimport.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllimport.cpp?rev=295258&r1=295257&r2=295258&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/dllimport.cpp (original) +++ cfe/trunk/test/CodeGenCXX/dllimport.cpp Wed Feb 15 17:28:10 2017 @@ -368,6 +368,13 @@ struct ClassWithCtor { ClassWithCtor() { struct __declspec(dllimport) ClassWithNonDllImportFieldWithCtor { ClassWithCtor t; }; USECLASS(ClassWithNonDllImportFieldWithCtor); // MO1-DAG: declare dllimport x86_thiscallcc %struct.ClassWithNonDllImportFieldWithCtor* @"\01??0ClassWithNonDllImportFieldWithCtor@@QAE@XZ"(%struct.ClassWithNonDllImportFieldWithCtor* returned) +struct ClassWithImplicitDtor { __declspec(dllimport) ClassWithImplicitDtor(); ClassWithDtor member; }; +__declspec(dllimport) inline void ReferencingDtorThroughDefinition() { ClassWithImplicitDtor x; }; +USE(ReferencingDtorThroughDefinition) +// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughDefinition@@YAXXZ"() +__declspec(dllimport) inline void ReferencingDtorThroughTemporary() { ClassWithImplicitDtor(); }; +USE(ReferencingDtorThroughTemporary) +// MO1-DAG: declare dllimport void @"\01?ReferencingDtorThroughTemporary@@YAXXZ"() // A dllimport function with a TLS variable must not be available_externally. __declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits