[clang] [clang][ssaf] CallGraph extrator should account for objc callees (PR #202606)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 9 06:13:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-ssaf
Author: Balázs Benics (steakhal)
<details>
<summary>Changes</summary>
Fixes: rdar://179104950
---
Full diff: https://github.com/llvm/llvm-project/pull/202606.diff
2 Files Affected:
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp (+7-3)
- (modified) clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp (+42)
``````````diff
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index 6e0b0ee8fe834..6dfb66a283674 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -72,9 +72,13 @@ void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
// never null.
assert(CalleeDecl);
- // FIXME: `clang::CallGraph` does not consider ObjCMessageExprs as calls.
- // Consequently, they don't appear as a Callee.
- assert(!isa<ObjCMethodDecl>(CalleeDecl));
+ // `clang::CallGraph` resolves ObjCMessageExprs (including property
+ // dot-syntax) to their ObjCMethodDecls and adds them as callees — see
+ // `CGBuilder::VisitObjCMessageExpr` in clang/lib/Analysis/CallGraph.cpp.
+ // ObjC dispatch is dynamic, so recording these as direct callees would be
+ // misleading; skip them until we model ObjC properly.
+ if (isa<ObjCMethodDecl>(CalleeDecl))
+ continue;
// FIXME: `clang::CallGraph` does not create entries for primary templates.
assert(!CalleeDecl->isTemplated());
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
index 39b3cf604857d..183fd7155cfba 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
@@ -424,6 +424,48 @@ TEST_F(CallGraphExtractorTest, ObjCMessageExprs) {
hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
}
+TEST_F(CallGraphExtractorTest, ObjCMessageToLocallyImplementedMethod) {
+ // When the receiver class is implemented in the same TU, `clang::CallGraph`
+ // resolves the ObjCMessageExpr (via `lookupPrivateMethod`) to an
+ // ObjCMethodDecl and adds it as a callee. The extractor must not abort on
+ // these — ObjC dispatch is dynamic and we don't model it as a direct callee.
+ runExtractor(R"cpp(
+ @interface NSObject @end
+ @interface Inner : NSObject
+ - (int) val;
+ @end
+ @implementation Inner
+ - (int) val { return 42; }
+ @end
+ int caller(Inner *x) { return [x val]; }
+ )cpp",
+ {"-x", "objective-c"});
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, ObjCPropertyDotSyntax) {
+ // Property dot-syntax (`x.val`) desugars to an ObjCMessageExpr to the
+ // synthesized getter; same dynamic dispatch as bracket syntax. Cover it
+ // explicitly because real-world hits often come through dot-syntax.
+ runExtractor(R"cpp(
+ @interface NSObject @end
+ @interface Inner : NSObject
+ @property (readonly) int val;
+ @end
+ @implementation Inner
+ @end
+ int caller(Inner *x) { return x.val; }
+ )cpp",
+ {"-x", "objective-c"});
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
TEST_F(CallGraphExtractorTest, DefinitionLocation) {
runExtractor(R"cpp(
void callee_with_def() {}
``````````
</details>
https://github.com/llvm/llvm-project/pull/202606
More information about the cfe-commits
mailing list