diff options
author | Hans Wennborg <hans@hanshq.net> | 2015-08-28 21:47:01 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2015-08-28 21:47:01 +0000 |
commit | 6eaa8323a887a878f54dfcc65d4fff72c0f5c161 (patch) | |
tree | 7dda0796d6e35b1752714167c273cb6bf0010ffc /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | e235d4502665e377cc920049dc33dfb693ad2067 (diff) | |
download | llvm-6eaa8323a887a878f54dfcc65d4fff72c0f5c161.zip llvm-6eaa8323a887a878f54dfcc65d4fff72c0f5c161.tar.gz llvm-6eaa8323a887a878f54dfcc65d4fff72c0f5c161.tar.bz2 |
Allow TLS vars in dllimport/export functions; only inline dllimport functions when safe (PR24593)
This patch does two things:
1) Don't error about dllimport/export on thread-local static local variables.
We put those attributes on static locals in dllimport/export functions
implicitly in case the function gets inlined. Now, for TLS variables this
is a problem because we can't import such variables, but it's a benign
problem becase:
2) Make sure we never inline a dllimport function TLS static locals. In fact,
never inline a dllimport function that references a non-imported function
or variable (because these are not defined in the importing library). This
seems to match MSVC's behaviour.
Differential Revision: http://reviews.llvm.org/D12422
llvm-svn: 246338
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0525869..847cb57 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1448,6 +1448,35 @@ namespace { return true; } }; + + struct DLLImportFunctionVisitor + : public RecursiveASTVisitor<DLLImportFunctionVisitor> { + bool SafeToInline = true; + + bool VisitVarDecl(VarDecl *VD) { + // A thread-local variable cannot be imported. + SafeToInline = !VD->getTLSKind(); + 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)) + SafeToInline = VD->hasAttr<DLLImportAttr>(); + else if (VarDecl *V = dyn_cast<VarDecl>(VD)) + SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>(); + return SafeToInline; + } + bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { + SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>(); + return SafeToInline; + } + bool VisitCXXNewExpr(CXXNewExpr *E) { + SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>(); + return SafeToInline; + } + }; } // isTriviallyRecursive - Check if this function calls another @@ -1478,6 +1507,15 @@ CodeGenModule::shouldEmitFunction(GlobalDecl GD) { const auto *F = cast<FunctionDecl>(GD.getDecl()); if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>()) return false; + + if (F->hasAttr<DLLImportAttr>()) { + // Check whether it would be safe to inline this dllimport function. + DLLImportFunctionVisitor Visitor; + Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F)); + if (!Visitor.SafeToInline) + return false; + } + // PR9614. Avoid cases where the source code is lying to us. An available // externally function should have an equivalent function somewhere else, // but a function that calls itself is clearly not equivalent to the real |