diff options
author | dim <dim@FreeBSD.org> | 2011-12-09 22:23:45 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-12-09 22:23:45 +0000 |
commit | 0a8d9e83286f1e0207031442c8c9b143758a0a75 (patch) | |
tree | 9f786c58105dd9ad2fee073528a513777fea3e3c /contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 1003872b67ebc3af8b693420f84097716d3b8395 (diff) | |
download | FreeBSD-src-0a8d9e83286f1e0207031442c8c9b143758a0a75.zip FreeBSD-src-0a8d9e83286f1e0207031442c8c9b143758a0a75.tar.gz |
Upgrade our copy of llvm/clang to 3.0 release. Release notes can be
found at: http://llvm.org/releases/3.0/docs/ReleaseNotes.html
MFC after: 1 week
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index 924ec84..275045c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -29,6 +29,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -858,6 +859,59 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { } } +namespace { + struct FunctionIsDirectlyRecursive : + public RecursiveASTVisitor<FunctionIsDirectlyRecursive> { + const StringRef Name; + bool Result; + FunctionIsDirectlyRecursive(const FunctionDecl *F) : + Name(F->getName()), Result(false) { + } + typedef RecursiveASTVisitor<FunctionIsDirectlyRecursive> Base; + + bool TraverseCallExpr(CallExpr *E) { + const Decl *D = E->getCalleeDecl(); + if (!D) + return true; + AsmLabelAttr *Attr = D->getAttr<AsmLabelAttr>(); + if (!Attr) + return true; + if (Name == Attr->getLabel()) { + Result = true; + return false; + } + return true; + } + }; +} + +// isTriviallyRecursiveViaAsm - Check if this function calls another +// decl that, because of the asm attribute, ends up pointing to itself. +bool +CodeGenModule::isTriviallyRecursiveViaAsm(const FunctionDecl *F) { + if (getCXXABI().getMangleContext().shouldMangleDeclName(F)) + return false; + + FunctionIsDirectlyRecursive Walker(F); + Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(F)); + return Walker.Result; +} + +bool +CodeGenModule::shouldEmitFunction(const FunctionDecl *F) { + if (getFunctionLinkage(F) != llvm::Function::AvailableExternallyLinkage) + return true; + if (CodeGenOpts.OptimizationLevel == 0 && + !F->hasAttr<AlwaysInlineAttr>()) + 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 + // implementation. + // This happens in glibc's btowc and in some configure checks. + return !isTriviallyRecursiveViaAsm(F); +} + void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { const ValueDecl *D = cast<ValueDecl>(GD.getDecl()); @@ -868,10 +922,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // At -O0, don't generate IR for functions with available_externally // linkage. - if (CodeGenOpts.OptimizationLevel == 0 && - !Function->hasAttr<AlwaysInlineAttr>() && - getFunctionLinkage(Function) - == llvm::Function::AvailableExternallyLinkage) + if (!shouldEmitFunction(Function)) return; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { |