From 60669c1cfed0ccf46cb8a655e017ad3ebbe8eab7 Mon Sep 17 00:00:00 2001 From: Prabhu Rajasekaran Date: Fri, 13 Mar 2026 16:24:22 -0700 Subject: [PATCH] Fix callee type generation (#186272) The callee_type metadata is expected to be a list of generalized type metadata by the IR verifier. But for indirect calls with internal linkage the type metadata is just an integer. Avoid including them in callee_type metadata. This will reduce the precision of the generated call graph as the edges to internal linkage functions whose address were taken will not be present anymore. We need to handle this in the future. --- clang/lib/CodeGen/CodeGenModule.cpp | 8 +++- .../CodeGen/call-graph-section-internal.cpp | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/call-graph-section-internal.cpp diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 3b64be7a477d..e0c508463a95 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3267,8 +3267,12 @@ void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD, void CodeGenModule::createCalleeTypeMetadataForIcall(const QualType &QT, llvm::CallBase *CB) { - // Only if needed for call graph section and only for indirect calls. - if (!CodeGenOpts.CallGraphSection || !CB->isIndirectCall()) + // Only if needed for call graph section and only for indirect calls that are + // visible externally. + // TODO: Handle local linkage symbols so they are not left out of call graph + // reducing precision. + if (!CodeGenOpts.CallGraphSection || !CB->isIndirectCall() || + !isExternallyVisible(QT->getLinkage())) return; llvm::Metadata *TypeIdMD = CreateMetadataIdentifierGeneralized(QT); diff --git a/clang/test/CodeGen/call-graph-section-internal.cpp b/clang/test/CodeGen/call-graph-section-internal.cpp new file mode 100644 index 000000000000..aea48675dfa2 --- /dev/null +++ b/clang/test/CodeGen/call-graph-section-internal.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -fexperimental-call-graph-section -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +// Check that we do not generate callee_type metadata for indirect calls +// to functions with internal linkage (e.g., types in anonymous namespaces), +// as their type metadata identifiers are distinct MDNodes instead of +// generalized strings, which would fail the LLVM Verifier. + +namespace { +class a; +class b { +public: + virtual void c(a); +}; +class a { +public: + b &e; + void d() { e.c(*this); } +}; + +void b::c(a) {} + +void f() { + a *g = nullptr; + g->d(); +} +} // namespace + +void test() { + f(); +} + +// CHECK-LABEL: define {{.*}} void @{{.*}}1a1dEv +// CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %{{.*}}, i{{[0-9]+}} 0 +// CHECK: %[[FP:.*]] = load ptr, ptr %[[VFN]], align {{[0-9]+}} +// CHECK: call void %[[FP]]({{.*}}) +// CHECK-NOT: !callee_type +// CHECK: ret void