r295258 - [dllimport] Check for dtor references in functions
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 15 15:28:10 PST 2017
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 at 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; }
More information about the cfe-commits
mailing list