[PATCH] D112059: Fix inline builtin handling in case of redefinition

serge via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 19 02:33:42 PDT 2021


serge-sans-paille created this revision.
serge-sans-paille added reviewers: nickdesaulniers, manojgupta.
serge-sans-paille requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Basically, inline builtin definition are shadowed by externally visible
redefinition. This matches GCC behavior.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112059

Files:
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/test/CodeGen/strlen-inline-builtin-redecl.c


Index: clang/test/CodeGen/strlen-inline-builtin-redecl.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/strlen-inline-builtin-redecl.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+//
+// Verifies that clang-generated *.inline are removed when shadowed by an external definition
+
+// CHECK-NOT: strlen.inline
+
+unsigned long strnlen(const char *, unsigned long);
+void fortify_panic(const char *);
+
+extern inline __attribute__((always_inline))
+__attribute__((gnu_inline)) unsigned long
+strlen(const char *p) {
+  unsigned long ret;
+  unsigned long p_size = __builtin_object_size(p, 0);
+
+  if (p_size == (unsigned long)-1 ||
+      (__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
+    return __builtin_strlen(p);
+  ret = strnlen(p, p_size);
+  if (p_size <= ret)
+    fortify_panic(__func__);
+  return ret;
+}
+char *strim(char *s) {
+  unsigned long size;
+  char *end;
+
+  size = strlen(s);
+  if (!size)
+    return s;
+
+  end = s + size - 1;
+  return end;
+}
+unsigned long strlen(const char *s) {
+  const char *sc;
+
+  for (sc = s; *sc != '\0'; ++sc)
+    ;
+  return sc - s;
+}
+extern typeof(strlen) strlen;
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1299,18 +1299,35 @@
   // When generating code for a builtin with an inline declaration, use a
   // mangled name to hold the actual body, while keeping an external definition
   // in case the function pointer is referenced somewhere.
-  if (FD->isInlineBuiltinDeclaration() && Fn) {
-    std::string FDInlineName = (Fn->getName() + ".inline").str();
-    llvm::Module *M = Fn->getParent();
-    llvm::Function *Clone = M->getFunction(FDInlineName);
-    if (!Clone) {
-      Clone = llvm::Function::Create(Fn->getFunctionType(),
-                                     llvm::GlobalValue::InternalLinkage,
-                                     Fn->getAddressSpace(), FDInlineName, M);
-      Clone->addFnAttr(llvm::Attribute::AlwaysInline);
+  if (Fn) {
+    if (FD->isInlineBuiltinDeclaration()) {
+      std::string FDInlineName = (Fn->getName() + ".inline").str();
+      llvm::Module *M = Fn->getParent();
+      llvm::Function *Clone = M->getFunction(FDInlineName);
+      if (!Clone) {
+        Clone = llvm::Function::Create(Fn->getFunctionType(),
+                                       llvm::GlobalValue::InternalLinkage,
+                                       Fn->getAddressSpace(), FDInlineName, M);
+        Clone->addFnAttr(llvm::Attribute::AlwaysInline);
+      }
+      Fn->setLinkage(llvm::GlobalValue::ExternalLinkage);
+      Fn = Clone;
+    }
+    // If the inline version is shadowed by a non-inline version, pick the
+    // external one. That's GCC behavior too.
+    else {
+      for (auto const *Redecl : FD->redecls()) {
+        if (Redecl->isInlineBuiltinDeclaration()) {
+          std::string FDInlineName = (Fn->getName() + ".inline").str();
+          llvm::Module *M = Fn->getParent();
+          llvm::Function *Clone = M->getFunction(FDInlineName);
+          if (Clone) {
+            Clone->replaceAllUsesWith(Fn);
+            Clone->eraseFromParent();
+          }
+        }
+      }
     }
-    Fn->setLinkage(llvm::GlobalValue::ExternalLinkage);
-    Fn = Clone;
   }
 
   // Check if we should generate debug info for this function.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D112059.380619.patch
Type: text/x-patch
Size: 3547 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211019/bd91c23c/attachment-0001.bin>


More information about the cfe-commits mailing list