https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/202606
Fixes: rdar://179104950 From d0f4933d334e6b7a39c58928134219cdd6014686 Mon Sep 17 00:00:00 2001 From: Balazs Benics <[email protected]> Date: Tue, 9 Jun 2026 14:03:06 +0100 Subject: [PATCH] [clang][ssaf] CallGraph extrator should account for objc callees Fixes: rdar://179104950 --- .../Analyses/CallGraph/CallGraphExtractor.cpp | 10 +++-- .../CallGraph/CallGraphExtractorTest.cpp | 42 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) 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() {} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
