Loading clang/lib/CodeGen/CodeGenModule.cpp +55 −4 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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()); Loading @@ -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)) { Loading clang/lib/CodeGen/CodeGenModule.h +2 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,8 @@ class CodeGenModule : public CodeGenTypeCache { void createOpenCLRuntime(); void createCUDARuntime(); bool isTriviallyRecursiveViaAsm(const FunctionDecl *F); bool shouldEmitFunction(const FunctionDecl *F); llvm::LLVMContext &VMContext; /// @name Cache for Blocks Runtime Globals Loading clang/test/CodeGen/pr9614.c 0 → 100644 +22 −0 Original line number Diff line number Diff line // RUN: %clang_cc1 -emit-llvm %s -O1 -o - | FileCheck %s extern void foo_alias (void) __asm ("foo"); inline void foo (void) { return foo_alias (); } extern void bar_alias (void) __asm ("bar"); inline __attribute__ ((__always_inline__)) void bar (void) { return bar_alias (); } void f(void) { foo(); bar(); } // CHECK: define void @f() // CHECK: call void @foo() // CHECK-NEXT: call void @bar() // CHECK-NEXT: ret void // CHECK: declare void @foo() // CHECK: declare void @bar() Loading
clang/lib/CodeGen/CodeGenModule.cpp +55 −4 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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()); Loading @@ -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)) { Loading
clang/lib/CodeGen/CodeGenModule.h +2 −0 Original line number Diff line number Diff line Loading @@ -324,6 +324,8 @@ class CodeGenModule : public CodeGenTypeCache { void createOpenCLRuntime(); void createCUDARuntime(); bool isTriviallyRecursiveViaAsm(const FunctionDecl *F); bool shouldEmitFunction(const FunctionDecl *F); llvm::LLVMContext &VMContext; /// @name Cache for Blocks Runtime Globals Loading
clang/test/CodeGen/pr9614.c 0 → 100644 +22 −0 Original line number Diff line number Diff line // RUN: %clang_cc1 -emit-llvm %s -O1 -o - | FileCheck %s extern void foo_alias (void) __asm ("foo"); inline void foo (void) { return foo_alias (); } extern void bar_alias (void) __asm ("bar"); inline __attribute__ ((__always_inline__)) void bar (void) { return bar_alias (); } void f(void) { foo(); bar(); } // CHECK: define void @f() // CHECK: call void @foo() // CHECK-NEXT: call void @bar() // CHECK-NEXT: ret void // CHECK: declare void @foo() // CHECK: declare void @bar()