From: Hans Wennborg Date: Mon, 23 Jan 2017 23:57:50 +0000 (+0000) Subject: Re-commit "Don't inline dllimport functions referencing non-imported methods" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9d63b56061c501aa9c02615e60b294a9e7a3b929;p=clang Re-commit "Don't inline dllimport functions referencing non-imported methods" This re-commits r292522 with the addition that it also handles calls through pointer to member functions without crashing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@292856 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c9d9a35fb8..f9866957a1 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1751,6 +1751,16 @@ namespace { SafeToInline = E->getConstructor()->hasAttr(); return SafeToInline; } + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { + CXXMethodDecl *M = E->getMethodDecl(); + if (!M) { + // Call through a pointer to member function. This is safe to inline. + SafeToInline = true; + } else { + SafeToInline = M->hasAttr(); + } + return SafeToInline; + } bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { SafeToInline = E->getOperatorDelete()->hasAttr(); return SafeToInline; diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 4ec14b7210..8e7ead9d1f 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -26,6 +26,7 @@ struct ExplicitSpec_NotImported {}; #define USEVARTYPE(type, var) type UNIQ(use)() { return var; } #define USEVAR(var) USEVARTYPE(int, var) #define USE(func) void UNIQ(use)() { func(); } +#define USE1(func) void UNIQ(use)() { func(nullptr); } #define USEMEMFUNC(class, func) void (class::*UNIQ(use)())() { return &class::func; } #define USESTATICMEMFUNC(class, func) void (*UNIQ(use)())() { return &class::func; } #define USECLASS(class) void UNIQ(USE)() { class x; } @@ -316,10 +317,13 @@ namespace ns { __declspec(dllimport) void externalFunc(); } USE(ns::externalFunc) // A dllimport function referencing non-imported vars or functions must not be available_externally. + __declspec(dllimport) int ImportedVar; int NonImportedVar; __declspec(dllimport) int ImportedFunc(); int NonImportedFunc(); +struct ClassWithNonImportedMethod { int f(); }; + __declspec(dllimport) inline int ReferencingImportedVar() { return ImportedVar; } // MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedVar@@YAHXZ" __declspec(dllimport) inline int ReferencingNonImportedVar() { return NonImportedVar; } @@ -328,10 +332,16 @@ __declspec(dllimport) inline int ReferencingImportedFunc() { return ImportedFunc // MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingImportedFunc@@YAHXZ" __declspec(dllimport) inline int ReferencingNonImportedFunc() { return NonImportedFunc(); } // MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedFunc@@YAHXZ"() +__declspec(dllimport) inline int ReferencingNonImportedMethod(ClassWithNonImportedMethod *x) { return x->f(); } +// MO1-DAG: declare dllimport i32 @"\01?ReferencingNonImportedMethod +__declspec(dllimport) inline int ReferencingClassMemberPtr(int (ClassWithNonImportedMethod::*p)(), ClassWithNonImportedMethod *x) { return (x->*p)(); } +// MO1-DAG: define available_externally dllimport i32 @"\01?ReferencingClassMemberPtr@@YAHP8ClassWithNonImportedMethod@@AEHXZPAU1@@Z" USE(ReferencingImportedVar) USE(ReferencingNonImportedVar) USE(ReferencingImportedFunc) USE(ReferencingNonImportedFunc) +USE1(ReferencingNonImportedMethod) +void UNIQ(use)() { ReferencingClassMemberPtr(&ClassWithNonImportedMethod::f, nullptr); } // References to operator new and delete count too, despite not being DeclRefExprs. __declspec(dllimport) inline int *ReferencingNonImportedNew() { return new int[2]; } // MO1-DAG: declare dllimport i32* @"\01?ReferencingNonImportedNew@@YAPAHXZ"