]> granicus.if.org Git - clang/commitdiff
Extend the fix for PR9614 to handle inline asm in the outer decl and
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 19 Dec 2011 14:41:01 +0000 (14:41 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 19 Dec 2011 14:41:01 +0000 (14:41 +0000)
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

lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGen/pr9614.c

index 0e8468f31d5c326a8426f400463ca92177659c24..16d01efb934b6d6ec5dbf42f129fcc863892807b 100644 (file)
@@ -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<FunctionIsDirectlyRecursive> {
     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<FunctionIsDirectlyRecursive> 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<AsmLabelAttr>();
-      if (!Attr)
+      AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
+      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<AsmLabelAttr>();
+    if (!Attr)
+      return false;
+    Name = Attr->getLabel();
+  } else {
+    Name = FD->getName();
+  }
 
-  FunctionIsDirectlyRecursive Walker(F);
-  Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
+  FunctionIsDirectlyRecursive Walker(Name, Context.BuiltinInfo);
+  Walker.TraverseFunctionDecl(const_cast<FunctionDecl*>(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) {
index 4c31737b29621a9b346917708ab32f2d8032b702..0517521d2cced86ea3023f92d1074a8052cfe00c 100644 (file)
@@ -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;
 
index 8c767766832da44fad12013701ed1e809fb1449a..228a4b3aaa5f686f43e0f158cbcd3a83c4ffb062 100644 (file)
@@ -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)