[clang] Fix interaction between asm labels and inline builtins
authorserge-sans-paille <sguelton@redhat.com>
Wed, 21 Sep 2022 14:08:45 +0000 (16:08 +0200)
committerserge-sans-paille <sguelton@redhat.com>
Thu, 22 Sep 2022 07:24:47 +0000 (09:24 +0200)
One must pick the same name as the one referenced in CodeGenFunction when
generating .inline version of an inline builtin, otherwise they are not
correctly replaced.

Differential Revision: https://reviews.llvm.org/D134362

clang/docs/ReleaseNotes.rst
clang/lib/CodeGen/CGExpr.cpp
clang/test/CodeGen/asm-label-inline-builtins.c [new file with mode: 0644]

index c50dd90..5d517eb 100644 (file)
@@ -162,6 +162,7 @@ Bug Fixes
   `Issue 53628 <https://github.com/llvm/llvm-project/issues/53628>`_
 - The template arguments of a variable template being accessed as a
   member will now be represented in the AST.
+- Fix incorrect handling of inline builtins with asm labels.
 
 
 Improvements to Clang's diagnostics
index d512459..80a05c9 100644 (file)
@@ -5051,7 +5051,10 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
   if (auto builtinID = FD->getBuiltinID()) {
     std::string NoBuiltinFD = ("no-builtin-" + FD->getName()).str();
     std::string NoBuiltins = "no-builtins";
-    std::string FDInlineName = (FD->getName() + ".inline").str();
+
+    auto *A = FD->getAttr<AsmLabelAttr>();
+    StringRef Ident = A ? A->getLabel() : FD->getName();
+    std::string FDInlineName = (Ident + ".inline").str();
 
     bool IsPredefinedLibFunction =
         CGF.getContext().BuiltinInfo.isPredefinedLibFunction(builtinID);
diff --git a/clang/test/CodeGen/asm-label-inline-builtins.c b/clang/test/CodeGen/asm-label-inline-builtins.c
new file mode 100644 (file)
index 0000000..ab9afc2
--- /dev/null
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+//
+// Verifies that clang-generated *.inline carry the same name at call and callee
+// site, in spite of asm labels.
+
+typedef struct _IO_FILE FILE;
+extern FILE *stdout;
+extern int vprintf (const char *__restrict __format, __builtin_va_list __arg);
+extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
+      const char *__restrict __format, __builtin_va_list __ap);
+extern int __vprintf_chk (int __flag, const char *__restrict __format,
+     __builtin_va_list __ap);
+
+extern __typeof (vprintf) vprintf __asm ("__vprintfieee128");
+extern __typeof (__vfprintf_chk) __vfprintf_chk __asm ("__vfprintf_chkieee128");
+extern __typeof (__vprintf_chk) __vprintf_chk __asm ("__vprintf_chkieee128");
+
+extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) __attribute__ ((__artificial__)) int
+vprintf (const char *__restrict __fmt, __builtin_va_list __ap)
+{
+  return __vfprintf_chk (stdout, 2 - 1, __fmt, __ap);
+}
+
+void test(const char *fmt, __builtin_va_list ap) {
+  vprintf(fmt, ap);
+}
+
+// CHECK-LABEL: void @test(
+// CHECK: call i32 @__vprintfieee128.inline(
+//
+// CHECK-LABEL: internal i32 @__vprintfieee128.inline(
+// CHECK: call i32 @__vfprintf_chkieee128(