https://github.com/Prabhuk updated 
https://github.com/llvm/llvm-project/pull/210846

>From 6a5c5f34f46f1a83d09d69b2781e7cd65e2728c3 Mon Sep 17 00:00:00 2001
From: prabhukr <[email protected]>
Date: Mon, 20 Jul 2026 23:30:26 +0000
Subject: [PATCH 1/5] [clang] Handle C11 style function signatures in call
 graph section

---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  4 ++++
 clang/lib/CodeGen/CGCall.cpp                  | 10 +++++++++-
 clang/lib/CodeGen/CGCall.h                    | 19 ++++++++++---------
 clang/lib/CodeGen/CGExpr.cpp                  |  5 +++--
 clang/test/CodeGen/call-graph-section.c       |  4 ++++
 5 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index a688b298f2bbd..b8db966e96ead 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -407,6 +407,10 @@ def warn_profile_data_misexpect : Warning<
   BackendInfo, InGroup<MisExpect>;
 } // end of instrumentation issue category
 
+def warn_cgs_no_proto : Warning<
+  "indirect call to a function with no prototype will be treated as a wildcard 
in the call graph section">,
+  InGroup<DiagGroup<"call-graph-section-no-prototype">>;
+
 def warn_ssaf_extract_tu_summary_file_unknown_output_format :
   Warning<"unknown output summary file format '%0' "
   "specified by '--ssaf-tu-summary-file=%1'">,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 08cb9860f2f92..50d3bc2747246 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -30,6 +30,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
@@ -6296,13 +6297,20 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
       else if (const auto *FPT =
                    Callee.getAbstractInfo().getCalleeFunctionProtoType())
         CST = QualType(FPT, 0);
+      else if (const auto *FT =
+                   Callee.getAbstractInfo().getCalleeFunctionType())
+        CST = QualType(FT, 0);
       else
         llvm_unreachable(
             "Cannot find the callee type to generate callee_type metadata.");
 
       // Set type identifier metadata of indirect calls for call graph section.
-      if (!CST.isNull())
+      if (!CST.isNull()) {
         CGM.createCalleeTypeMetadataForIcall(CST, *callOrInvoke);
+        if (!CST->isFunctionProtoType() &&
+            CGM.getCodeGenOpts().CallGraphSection)
+          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto);
+      }
     }
   }
 
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index 5df7f0d08d070..9c5ffe89367e3 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -41,22 +41,23 @@ namespace CodeGen {
 
 /// Abstract information about a function or function prototype.
 class CGCalleeInfo {
-  /// The function prototype of the callee.
-  const FunctionProtoType *CalleeProtoTy;
+  /// The function type of the callee.
+  const FunctionType *CalleeFunctionTy;
   /// The function declaration of the callee.
   GlobalDecl CalleeDecl;
 
 public:
-  explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}
-  CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
-      : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
-  CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
-      : CalleeProtoTy(calleeProtoTy) {}
+  explicit CGCalleeInfo() : CalleeFunctionTy(nullptr) {}
+  CGCalleeInfo(const FunctionType *calleeFunctionTy, GlobalDecl calleeDecl)
+      : CalleeFunctionTy(calleeFunctionTy), CalleeDecl(calleeDecl) {}
+  CGCalleeInfo(const FunctionType *calleeFunctionTy)
+      : CalleeFunctionTy(calleeFunctionTy) {}
   CGCalleeInfo(GlobalDecl calleeDecl)
-      : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
+      : CalleeFunctionTy(nullptr), CalleeDecl(calleeDecl) {}
 
+  const FunctionType *getCalleeFunctionType() const { return CalleeFunctionTy; 
}
   const FunctionProtoType *getCalleeFunctionProtoType() const {
-    return CalleeProtoTy;
+    return dyn_cast_or_null<FunctionProtoType>(CalleeFunctionTy);
   }
   const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
 };
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index dd42e9550316d..383a5f50b57a8 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6646,7 +6646,8 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
                 dyn_cast_or_null<VarDecl>(E->getReferencedDeclOfCallee())) {
           GD = GlobalDecl(VD);
         }
-        CGCalleeInfo CalleeInfo(FunctionType->getAs<FunctionProtoType>(), GD);
+        CGCalleeInfo CalleeInfo(FunctionType->castAs<clang::FunctionType>(),
+                                GD);
         CGCallee Callee(CalleeInfo, ConvertFuncrefToPtr(Result.first),
                         Result.second);
         return Callee;
@@ -6690,7 +6691,7 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
           dyn_cast_or_null<VarDecl>(E->getReferencedDeclOfCallee()))
     GD = GlobalDecl(VD);
 
-  CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD);
+  CGCalleeInfo calleeInfo(functionType->castAs<clang::FunctionType>(), GD);
   CGPointerAuthInfo pointerAuth = CGM.getFunctionPointerAuthInfo(functionType);
   CGCallee callee(calleeInfo, ConvertFuncrefToPtr(calleePtr), pointerAuth);
   return callee;
diff --git a/clang/test/CodeGen/call-graph-section.c 
b/clang/test/CodeGen/call-graph-section.c
index cb2f9015b7ff5..52899ef20b790 100644
--- a/clang/test/CodeGen/call-graph-section.c
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -6,6 +6,9 @@
 // RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
 // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
 
+// RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck --check-prefixes=WARNING %s
+
 // CHECK-LABEL: define {{(dso_local)?}} void @foo(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
 void foo() {
@@ -17,6 +20,7 @@ void bar() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // WARNING: warning: indirect call to a function with no prototype will be 
treated as a wildcard in the call graph section 
[-Wcall-graph-section-no-prototype]
   fp();
 }
 

>From fac539dad6f5c6cdef04b3f7864c7f652713556c Mon Sep 17 00:00:00 2001
From: prabhukr <[email protected]>
Date: Tue, 21 Jul 2026 00:22:30 +0000
Subject: [PATCH 2/5] Improve warning text.

---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 +-
 clang/lib/CodeGen/CGCall.cpp                  | 11 ++++--
 clang/test/CodeGen/call-graph-section.c       | 36 +++++++++++++++++--
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index b8db966e96ead..ee85fd288fc1f 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -408,7 +408,7 @@ def warn_profile_data_misexpect : Warning<
 } // end of instrumentation issue category
 
 def warn_cgs_no_proto : Warning<
-  "indirect call to a function with no prototype will be treated as a wildcard 
in the call graph section">,
+  "indirect call to a function with no prototype; generating type metadata as 
if it took no arguments (type: %0, type string: %1)%select{| even though 
arguments are passed at this call site}2">,
   InGroup<DiagGroup<"call-graph-section-no-prototype">>;
 
 def warn_ssaf_extract_tu_summary_file_unknown_output_format :
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 50d3bc2747246..c54686481fee5 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6308,8 +6308,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
       if (!CST.isNull()) {
         CGM.createCalleeTypeMetadataForIcall(CST, *callOrInvoke);
         if (!CST->isFunctionProtoType() &&
-            CGM.getCodeGenOpts().CallGraphSection)
-          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto);
+            CGM.getCodeGenOpts().CallGraphSection) {
+          llvm::Metadata *MD =
+              CGM.CreateMetadataIdentifierForCallGraphType(CST);
+          StringRef TypeStr;
+          if (auto *MDS = dyn_cast_or_null<llvm::MDString>(MD))
+            TypeStr = MDS->getString();
+          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto)
+              << CST << TypeStr << !CallArgs.empty();
+        }
       }
     }
   }
diff --git a/clang/test/CodeGen/call-graph-section.c 
b/clang/test/CodeGen/call-graph-section.c
index 52899ef20b790..60af5ee18fe5d 100644
--- a/clang/test/CodeGen/call-graph-section.c
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -7,7 +7,7 @@
 // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
 
 // RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
-// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck --check-prefixes=WARNING %s
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE %s
 
 // CHECK-LABEL: define {{(dso_local)?}} void @foo(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
@@ -20,7 +20,7 @@ void bar() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARNING: warning: indirect call to a function with no prototype will be 
treated as a wildcard in the call graph section 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) [-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -78,6 +78,34 @@ void stf() {
   fp_stparam(St2, &St2);
 }
 
+struct my_struct;
+
+// CHECK-LABEL: define {{(dso_local)?}} ptr @create_my_struct(
+// CHECK-SAME: {{.*}} !callgraph [[F_TMY_STRUCT:![0-9]+]]
+struct my_struct *create_my_struct() {
+  return 0;
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @test_struct_ptr_return(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void test_struct_ptr_return() {
+  struct my_struct *(*fp)() = create_my_struct;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: _ZTSFP9my_structE) 
[-Wcall-graph-section-no-prototype]
+  fp();
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @test_no_proto_with_args(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void test_no_proto_with_args() {
+  void (*fp)() = foo;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
+  fp(1);
+}
+
 // ITANIUM: [[F_TVOID]] = !{!"_ZTSFvE"}
 // ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
 // ITANIUM: [[F_TPRIMITIVE]] = !{!"_ZTSFicfdE"}
@@ -86,6 +114,8 @@ void stf() {
 // ITANIUM: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
 // ITANIUM: [[F_TSTRUCT]] = !{!"_ZTSFv3st2PS_E"}
 // ITANIUM: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}
+// ITANIUM: [[F_TMY_STRUCT]] = !{!"_ZTSFP9my_structE"}
+// ITANIUM: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
 
 // MS: [[F_TVOID]] = !{!"?6AX@Z"}
 // MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
@@ -95,3 +125,5 @@ void stf() {
 // MS: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
 // MS: [[F_TSTRUCT]] = !{!"?6AXUst2@@PEAU0@@Z"}
 // MS: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}
+// MS: [[F_TMY_STRUCT]] = !{!"?6APEAUmy_struct@@@Z"}
+// MS: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}

>From 4459945f20f1095fd5d5e4184c4becfec9790af8 Mon Sep 17 00:00:00 2001
From: prabhukr <[email protected]>
Date: Tue, 21 Jul 2026 17:36:02 +0000
Subject: [PATCH 3/5] Include MS ABI warnings too.

---
 clang/test/CodeGen/call-graph-section.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGen/call-graph-section.c 
b/clang/test/CodeGen/call-graph-section.c
index 60af5ee18fe5d..7a5f9efe322cb 100644
--- a/clang/test/CodeGen/call-graph-section.c
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -7,7 +7,10 @@
 // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
 
 // RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
-// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE %s
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_ITANIUM %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_MS %s
 
 // CHECK-LABEL: define {{(dso_local)?}} void @foo(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
@@ -20,7 +23,8 @@ void bar() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: ?6AX@Z) [-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -92,7 +96,8 @@ void test_struct_ptr_return() {
   struct my_struct *(*fp)() = create_my_struct;
   // ITANIUM: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: _ZTSFP9my_structE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: _ZTSFP9my_structE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: ?6APEAUmy_struct@@@Z) 
[-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -102,7 +107,8 @@ void test_no_proto_with_args() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: ?6AX@Z) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
   fp(1);
 }
 

>From ef97b722fd89d2829c1ae045445becc5726dcb32 Mon Sep 17 00:00:00 2001
From: prabhukr <[email protected]>
Date: Tue, 21 Jul 2026 20:30:39 +0000
Subject: [PATCH 4/5] Treat function type as variadic.

---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 +-
 clang/lib/CodeGen/CGCall.cpp                  |  3 +-
 clang/lib/CodeGen/CodeGenModule.cpp           |  8 +++
 .../CodeGen/call-graph-section-noprototype.c  | 71 +++++++++++++++++++
 clang/test/CodeGen/call-graph-section.c       | 56 ++-------------
 5 files changed, 88 insertions(+), 52 deletions(-)
 create mode 100644 clang/test/CodeGen/call-graph-section-noprototype.c

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ee85fd288fc1f..35e65a02bde09 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -408,7 +408,7 @@ def warn_profile_data_misexpect : Warning<
 } // end of instrumentation issue category
 
 def warn_cgs_no_proto : Warning<
-  "indirect call to a function with no prototype; generating type metadata as 
if it took no arguments (type: %0, type string: %1)%select{| even though 
arguments are passed at this call site}2">,
+  "indirect call to a function with no prototype; generating callee_type 
metadata as if calling a variadic function (type: %0, type string: %1)">,
   InGroup<DiagGroup<"call-graph-section-no-prototype">>;
 
 def warn_ssaf_extract_tu_summary_file_unknown_output_format :
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index a5f14bc95a94f..e99d172523cd4 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6368,8 +6368,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
           StringRef TypeStr;
           if (auto *MDS = dyn_cast_or_null<llvm::MDString>(MD))
             TypeStr = MDS->getString();
-          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto)
-              << CST << TypeStr << !CallArgs.empty();
+          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto) << CST << 
TypeStr;
         }
       }
     }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 8ce4063a3b780..6c955ace0c9f8 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -8651,6 +8651,14 @@ llvm::Metadata 
*CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) {
 
 llvm::Metadata *
 CodeGenModule::CreateMetadataIdentifierForCallGraphType(QualType T) {
+  if (auto *FNPT = T->getAs<FunctionNoProtoType>()) {
+    // For no-prototype functions, treat them as if they are variadic functions
+    // as we cannot determine the arguments for calls to these functions from
+    // call sites.
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.Variadic = true;
+    T = getContext().getFunctionType(FNPT->getReturnType(), {}, EPI);
+  }
   return CreateMetadataIdentifierImpl(T, CallGraphMetadataIdMap, "",
                                       /*ForceString=*/true);
 }
diff --git a/clang/test/CodeGen/call-graph-section-noprototype.c 
b/clang/test/CodeGen/call-graph-section-noprototype.c
new file mode 100644
index 0000000000000..8847481be9e4c
--- /dev/null
+++ b/clang/test/CodeGen/call-graph-section-noprototype.c
@@ -0,0 +1,71 @@
+// Tests that we assign appropriate identifiers to indirect calls and targets
+// for no-prototype functions which are treated as if they are variadic 
functions
+// in generating their type strings for call graph section.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_ITANIUM %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_MS %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,ITANIUM %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
+// RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
+
+// CHECK-LABEL: define {{(dso_local)?}} void @foo(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
+void foo() {
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @bar(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void bar() {
+  void (*fp)() = foo;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: _ZTSFvzE) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
+  fp();
+}
+
+struct my_struct;
+
+// CHECK-LABEL: define {{(dso_local)?}} ptr @create_my_struct(
+// CHECK-SAME: {{.*}} !callgraph [[F_TMY_STRUCT:![0-9]+]]
+struct my_struct *create_my_struct() {
+  return 0;
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @test_struct_ptr_return(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void test_struct_ptr_return() {
+  struct my_struct *(*fp)() = create_my_struct;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'struct my_struct *()', type string: _ZTSFP9my_structzE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'struct my_struct *()', type string: ?6APEAUmy_struct@@ZZ) 
[-Wcall-graph-section-no-prototype]
+  fp();
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @test_no_proto_with_args(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void test_no_proto_with_args() {
+  void (*fp)() = foo;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: _ZTSFvzE) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
+  fp(1);
+}
+
+// ITANIUM: [[F_TVOID]] = !{!"_ZTSFvzE"}
+// ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
+// ITANIUM: [[F_TMY_STRUCT]] = !{!"_ZTSFP9my_structzE"}
+// ITANIUM: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
+
+// MS: [[F_TVOID]] = !{!"?6AXZZ"}
+// MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
+// MS: [[F_TMY_STRUCT]] = !{!"?6APEAUmy_struct@@ZZ"}
+// MS: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
diff --git a/clang/test/CodeGen/call-graph-section.c 
b/clang/test/CodeGen/call-graph-section.c
index 7a5f9efe322cb..5019d18425ec6 100644
--- a/clang/test/CodeGen/call-graph-section.c
+++ b/clang/test/CodeGen/call-graph-section.c
@@ -6,25 +6,17 @@
 // RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
 // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s
 
-// RUN: %clang_cc1 -triple x86_64-unknown-linux 
-fexperimental-call-graph-section \
-// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_ITANIUM %s
-
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc 
-fexperimental-call-graph-section \
-// RUN: -emit-llvm -o /dev/null %s 2>&1 | FileCheck 
--check-prefixes=WARN_NO_PROTOTYPE_MS %s
-
 // CHECK-LABEL: define {{(dso_local)?}} void @foo(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]]
-void foo() {
+void foo(void) {
 }
 
 // CHECK-LABEL: define {{(dso_local)?}} void @bar(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
-void bar() {
-  void (*fp)() = foo;
+void bar(void) {
+  void (*fp)(void) = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) [-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: ?6AX@Z) [-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -42,7 +34,7 @@ int *qux(char *a, float *b, double *c) {
 
 // CHECK-LABEL: define {{(dso_local)?}} void @corge(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
-void corge() {
+void corge(void) {
   int (*fp_baz)(char, float, double) = baz;  
   // CHECK: call i32 {{.*}}, !callee_type [[F_TPRIMITIVE_CT:![0-9]+]]
   fp_baz('a', .0f, .0);
@@ -66,7 +58,7 @@ void stparam(struct st2 a, struct st2 *b) {}
 
 // CHECK-LABEL: define {{(dso_local)?}} void @stf(
 // CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
-void stf() {
+void stf(void) {
   struct st1 St1;
   St1.fp = qux;  
   // CHECK: call ptr {{.*}}, !callee_type [[F_TPTR_CT:![0-9]+]]
@@ -82,37 +74,7 @@ void stf() {
   fp_stparam(St2, &St2);
 }
 
-struct my_struct;
-
-// CHECK-LABEL: define {{(dso_local)?}} ptr @create_my_struct(
-// CHECK-SAME: {{.*}} !callgraph [[F_TMY_STRUCT:![0-9]+]]
-struct my_struct *create_my_struct() {
-  return 0;
-}
-
-// CHECK-LABEL: define {{(dso_local)?}} void @test_struct_ptr_return(
-// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
-void test_struct_ptr_return() {
-  struct my_struct *(*fp)() = create_my_struct;
-  // ITANIUM: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
-  // MS: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: _ZTSFP9my_structE) 
[-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'struct 
my_struct *()', type string: ?6APEAUmy_struct@@@Z) 
[-Wcall-graph-section-no-prototype]
-  fp();
-}
-
-// CHECK-LABEL: define {{(dso_local)?}} void @test_no_proto_with_args(
-// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
-void test_no_proto_with_args() {
-  void (*fp)() = foo;
-  // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: _ZTSFvE) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating type metadata as if it took no arguments (type: 'void 
()', type string: ?6AX@Z) even though arguments are passed at this call site 
[-Wcall-graph-section-no-prototype]
-  fp(1);
-}
-
-// ITANIUM: [[F_TVOID]] = !{!"_ZTSFvE"}
+// ITANIUM: [[F_TVOID]] = !{!"_ZTSFvvE"}
 // ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
 // ITANIUM: [[F_TPRIMITIVE]] = !{!"_ZTSFicfdE"}
 // ITANIUM: [[F_TPTR]] = !{!"_ZTSFPiPcPfPdE"}
@@ -120,10 +82,8 @@ void test_no_proto_with_args() {
 // ITANIUM: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
 // ITANIUM: [[F_TSTRUCT]] = !{!"_ZTSFv3st2PS_E"}
 // ITANIUM: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}
-// ITANIUM: [[F_TMY_STRUCT]] = !{!"_ZTSFP9my_structE"}
-// ITANIUM: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
 
-// MS: [[F_TVOID]] = !{!"?6AX@Z"}
+// MS: [[F_TVOID]] = !{!"?6AXXZ"}
 // MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
 // MS: [[F_TPRIMITIVE]] = !{!"?6AHDMN@Z"}
 // MS: [[F_TPTR]] = !{!"?6APEAHPEADPEAMPEAN@Z"}
@@ -131,5 +91,3 @@ void test_no_proto_with_args() {
 // MS: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]}
 // MS: [[F_TSTRUCT]] = !{!"?6AXUst2@@PEAU0@@Z"}
 // MS: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]}
-// MS: [[F_TMY_STRUCT]] = !{!"?6APEAUmy_struct@@@Z"}
-// MS: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}

>From 2a1c847879181180879786d4ae472307a861327d Mon Sep 17 00:00:00 2001
From: prabhukr <[email protected]>
Date: Tue, 21 Jul 2026 20:55:13 +0000
Subject: [PATCH 5/5] Print assumed type in the warning. Add a test case with
 non-void return type.

---
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 +-
 clang/lib/CodeGen/CGCall.cpp                  | 12 ++++++-
 .../CodeGen/call-graph-section-noprototype.c  | 33 +++++++++++++++----
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 35e65a02bde09..3abf39aed704d 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -408,7 +408,7 @@ def warn_profile_data_misexpect : Warning<
 } // end of instrumentation issue category
 
 def warn_cgs_no_proto : Warning<
-  "indirect call to a function with no prototype; generating callee_type 
metadata as if calling a variadic function (type: %0, type string: %1)">,
+  "indirect call to a function with no prototype %0; generating callee_type 
metadata as if calling a variadic function %1 (type string: %2)">,
   InGroup<DiagGroup<"call-graph-section-no-prototype">>;
 
 def warn_ssaf_extract_tu_summary_file_unknown_output_format :
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index e99d172523cd4..cb630864c5eeb 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6368,7 +6368,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
           StringRef TypeStr;
           if (auto *MDS = dyn_cast_or_null<llvm::MDString>(MD))
             TypeStr = MDS->getString();
-          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto) << CST << 
TypeStr;
+
+          QualType AssumedType = CST;
+          if (auto *FNPT = CST->getAs<FunctionNoProtoType>()) {
+            FunctionProtoType::ExtProtoInfo EPI;
+            EPI.Variadic = true;
+            AssumedType = CGM.getContext().getFunctionType(
+                FNPT->getReturnType(), {}, EPI);
+          }
+
+          CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto)
+              << CST << AssumedType << TypeStr;
         }
       }
     }
diff --git a/clang/test/CodeGen/call-graph-section-noprototype.c 
b/clang/test/CodeGen/call-graph-section-noprototype.c
index 8847481be9e4c..dc89daf956bc6 100644
--- a/clang/test/CodeGen/call-graph-section-noprototype.c
+++ b/clang/test/CodeGen/call-graph-section-noprototype.c
@@ -25,8 +25,8 @@ void bar() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: _ZTSFvzE) [-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype 'void ()'; generating callee_type metadata as if calling a variadic 
function 'void (...)' (type string: _ZTSFvzE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype 'void ()'; generating callee_type metadata as if calling a variadic 
function 'void (...)' (type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -44,8 +44,25 @@ void test_struct_ptr_return() {
   struct my_struct *(*fp)() = create_my_struct;
   // ITANIUM: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TMY_STRUCT_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'struct my_struct *()', type string: _ZTSFP9my_structzE) 
[-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'struct my_struct *()', type string: ?6APEAUmy_struct@@ZZ) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype 'struct my_struct *()'; generating callee_type metadata as if calling 
a variadic function 'struct my_struct *(...)' (type string: _ZTSFP9my_structzE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype 'struct my_struct *()'; generating callee_type metadata as if calling 
a variadic function 'struct my_struct *(...)' (type string: 
?6APEAUmy_struct@@ZZ) [-Wcall-graph-section-no-prototype]
+  fp();
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} i32 @baz(
+// CHECK-SAME: {{.*}} !callgraph [[F_TINT:![0-9]+]]
+int baz() {
+  return 1;
+}
+
+// CHECK-LABEL: define {{(dso_local)?}} void @test_int_return(
+// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]]
+void test_int_return() {
+  int (*fp)() = baz;
+  // ITANIUM: call {{.*}}, !callee_type [[F_TINT_CT:![0-9]+]]
+  // MS: call {{.*}}, !callee_type [[F_TINT_CT:![0-9]+]]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype 'int ()'; generating callee_type metadata as if calling a variadic 
function 'int (...)' (type string: _ZTSFizE) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype 'int ()'; generating callee_type metadata as if calling a variadic 
function 'int (...)' (type string: ?6AHZZ) [-Wcall-graph-section-no-prototype]
   fp();
 }
 
@@ -55,8 +72,8 @@ void test_no_proto_with_args() {
   void (*fp)() = foo;
   // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
   // MS: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]]
-  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: _ZTSFvzE) [-Wcall-graph-section-no-prototype]
-  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype; generating callee_type metadata as if calling a variadic function 
(type: 'void ()', type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_ITANIUM: warning: indirect call to a function with no 
prototype 'void ()'; generating callee_type metadata as if calling a variadic 
function 'void (...)' (type string: _ZTSFvzE) 
[-Wcall-graph-section-no-prototype]
+  // WARN_NO_PROTOTYPE_MS: warning: indirect call to a function with no 
prototype 'void ()'; generating callee_type metadata as if calling a variadic 
function 'void (...)' (type string: ?6AXZZ) [-Wcall-graph-section-no-prototype]
   fp(1);
 }
 
@@ -64,8 +81,12 @@ void test_no_proto_with_args() {
 // ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
 // ITANIUM: [[F_TMY_STRUCT]] = !{!"_ZTSFP9my_structzE"}
 // ITANIUM: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
+// ITANIUM: [[F_TINT]] = !{!"_ZTSFizE"}
+// ITANIUM: [[F_TINT_CT]] = !{[[F_TINT:![0-9]+]]}
 
 // MS: [[F_TVOID]] = !{!"?6AXZZ"}
 // MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]}
 // MS: [[F_TMY_STRUCT]] = !{!"?6APEAUmy_struct@@ZZ"}
 // MS: [[F_TMY_STRUCT_CT]] = !{[[F_TMY_STRUCT:![0-9]+]]}
+// MS: [[F_TINT]] = !{!"?6AHZZ"}
+// MS: [[F_TINT_CT]] = !{[[F_TINT:![0-9]+]]}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to