[clang] [clang] Do not diagnose conflicting types for cfi_unchecked_callee (PR #157762)

via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 16 22:05:30 PDT 2025


https://github.com/PiJoules updated https://github.com/llvm/llvm-project/pull/157762

>From b88fb87e1627b91b83f25a27cd10f9cdddc860f0 Mon Sep 17 00:00:00 2001
From: Leonard Chan <leonardchan at google.com>
Date: Tue, 9 Sep 2025 15:25:56 -0700
Subject: [PATCH] [clang] Do not diagnose conflicting types for
 cfi_unchecked_callee

Clang would complain about conflicting types between a function
declaration and definition if the declaraion was marked with the
attribute but the definition wasn't. Do not treat this as an error. It
should only be necessary to mark the declaration with the attribute.
---
 clang/docs/ReleaseNotes.rst                     |  3 +++
 clang/lib/Sema/SemaDecl.cpp                     | 17 +++++++++++++++++
 clang/test/AST/cfi-unchecked-callee.cpp         |  9 +++++++++
 .../Frontend/cfi-unchecked-callee-attribute.cpp |  4 ++++
 4 files changed, 33 insertions(+)
 create mode 100644 clang/test/AST/cfi-unchecked-callee.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9af55951a1d82..e5e241f65227b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -233,6 +233,9 @@ Removed Compiler Flags
 
 Attribute Changes in Clang
 --------------------------
+- The definition of a function declaration with ``[[clang::cfi_unchecked_callee]]`` inherits this
+  attribute, allowing the attribute to only be attached to the declaration. Prior, this would be
+  treated as an error where the definition and declaration would have differing types.
 
 Improvements to Clang's diagnostics
 -----------------------------------
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 45cfb66996ce6..e10511cc7fc4e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3877,6 +3877,23 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
     RequiresAdjustment = true;
   }
 
+  // If the declaration is marked with cfi_unchecked_callee but the definition
+  // isn't, the definition is also cfi_unchecked_callee.
+  if (auto *FPT1 = OldType->getAs<FunctionProtoType>()) {
+    if (auto *FPT2 = NewType->getAs<FunctionProtoType>()) {
+      FunctionProtoType::ExtProtoInfo EPI1 = FPT1->getExtProtoInfo();
+      FunctionProtoType::ExtProtoInfo EPI2 = FPT2->getExtProtoInfo();
+
+      if (EPI1.CFIUncheckedCallee && !EPI2.CFIUncheckedCallee) {
+        EPI2.CFIUncheckedCallee = true;
+        NewQType = Context.getFunctionType(FPT2->getReturnType(),
+                                           FPT2->getParamTypes(), EPI2);
+        NewType = cast<FunctionType>(NewQType);
+        New->setType(NewQType);
+      }
+    }
+  }
+
   // Merge regparm attribute.
   if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() ||
       OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
diff --git a/clang/test/AST/cfi-unchecked-callee.cpp b/clang/test/AST/cfi-unchecked-callee.cpp
new file mode 100644
index 0000000000000..af84996835930
--- /dev/null
+++ b/clang/test/AST/cfi-unchecked-callee.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -ast-dump %s | FileCheck %s
+
+
+// CHECK: FunctionDecl [[PTR:0x[a-z0-9]*]] {{.*}}func 'void () __attribute__((cfi_unchecked_callee))'
+__attribute__((cfi_unchecked_callee))
+void func(void);
+
+// CHECK-NEXT: FunctionDecl {{0x[a-z0-9]*}} prev [[PTR]] {{.*}}func 'void () __attribute__((cfi_unchecked_callee))'
+void func(void) {}
diff --git a/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp b/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp
index f2c4e9e2f8890..072f217ff7b19 100644
--- a/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp
+++ b/clang/test/Frontend/cfi-unchecked-callee-attribute.cpp
@@ -233,3 +233,7 @@ void lambdas() {
     checked_func = checked_lambda;
   };
 }
+
+CFI_UNCHECKED_CALLEE
+void func(void);
+void func(void) {}  // No warning expected.



More information about the cfe-commits mailing list