From: Rafael Espindola Date: Mon, 19 Dec 2011 14:41:01 +0000 (+0000) Subject: Extend the fix for PR9614 to handle inline asm in the outer decl and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bcf6b98247bd3ac76c5edf706b1087a8d32c0320;p=clang Extend the fix for PR9614 to handle inline asm in the outer decl and the inner decl being a builtin. This is needed to support the glibc headers in fedora 16 (2.14). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146867 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0e8468f31d..16d01efb93 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -30,6 +30,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -863,20 +864,27 @@ namespace { struct FunctionIsDirectlyRecursive : public RecursiveASTVisitor { const StringRef Name; + const Builtin::Context &BI; bool Result; - FunctionIsDirectlyRecursive(const FunctionDecl *F) : - Name(F->getName()), Result(false) { + FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C) : + Name(N), BI(C), Result(false) { } typedef RecursiveASTVisitor Base; bool TraverseCallExpr(CallExpr *E) { - const Decl *D = E->getCalleeDecl(); - if (!D) + const FunctionDecl *FD = E->getDirectCallee(); + if (!FD) return true; - AsmLabelAttr *Attr = D->getAttr(); - if (!Attr) + AsmLabelAttr *Attr = FD->getAttr(); + if (Attr && Name == Attr->getLabel()) { + Result = true; + return false; + } + unsigned BuiltinID = FD->getBuiltinID(); + if (!BuiltinID) return true; - if (Name == Attr->getLabel()) { + const char *BuiltinName = BI.GetName(BuiltinID) + strlen("__builtin_"); + if (Name == BuiltinName) { Result = true; return false; } @@ -885,15 +893,24 @@ namespace { }; } -// isTriviallyRecursiveViaAsm - Check if this function calls another -// decl that, because of the asm attribute, ends up pointing to itself. +// isTriviallyRecursive - Check if this function calls another +// decl that, because of the asm attribute or the other decl being a builtin, +// ends up pointing to itself. bool -CodeGenModule::isTriviallyRecursiveViaAsm(const FunctionDecl *F) { - if (getCXXABI().getMangleContext().shouldMangleDeclName(F)) - return false; +CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) { + StringRef Name; + if (getCXXABI().getMangleContext().shouldMangleDeclName(FD)) { + // asm labels are a special king of mangling we have to support. + AsmLabelAttr *Attr = FD->getAttr(); + if (!Attr) + return false; + Name = Attr->getLabel(); + } else { + Name = FD->getName(); + } - FunctionIsDirectlyRecursive Walker(F); - Walker.TraverseFunctionDecl(const_cast(F)); + FunctionIsDirectlyRecursive Walker(Name, Context.BuiltinInfo); + Walker.TraverseFunctionDecl(const_cast(FD)); return Walker.Result; } @@ -909,7 +926,7 @@ CodeGenModule::shouldEmitFunction(const FunctionDecl *F) { // 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); + return !isTriviallyRecursive(F); } void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 4c31737b29..0517521d2c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -323,7 +323,7 @@ class CodeGenModule : public CodeGenTypeCache { void createOpenCLRuntime(); void createCUDARuntime(); - bool isTriviallyRecursiveViaAsm(const FunctionDecl *F); + bool isTriviallyRecursive(const FunctionDecl *F); bool shouldEmitFunction(const FunctionDecl *F); llvm::LLVMContext &VMContext; diff --git a/test/CodeGen/pr9614.c b/test/CodeGen/pr9614.c index 8c76776683..228a4b3aaa 100644 --- a/test/CodeGen/pr9614.c +++ b/test/CodeGen/pr9614.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s extern void foo_alias (void) __asm ("foo"); inline void foo (void) { @@ -8,15 +8,22 @@ extern void bar_alias (void) __asm ("bar"); inline __attribute__ ((__always_inline__)) void bar (void) { return bar_alias (); } +extern char *strrchr_foo (const char *__s, int __c) __asm ("strrchr"); +extern inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) char * strrchr_foo (const char *__s, int __c) { + return __builtin_strrchr (__s, __c); +} void f(void) { foo(); bar(); + strrchr_foo("", '.'); } // CHECK: define void @f() // CHECK: call void @foo() // CHECK-NEXT: call void @bar() +// CHECK-NEXT: call i8* @strrchr( // CHECK-NEXT: ret void // CHECK: declare void @foo() // CHECK: declare void @bar() +// CHECK: declare i8* @strrchr(i8*, i32)