https://github.com/bazuzi updated https://github.com/llvm/llvm-project/pull/73978
>From aab1069636896c4a8289545ba01d2fdf4f1715c0 Mon Sep 17 00:00:00 2001 From: Samira Bazuzi <baz...@google.com> Date: Thu, 30 Nov 2023 14:18:04 -0500 Subject: [PATCH 1/4] [clang][dataflow] Retrieve members from accessors called using member pointers. getMethodDecl does not handle pointers to members and returns nullptr. --- .../FlowSensitive/DataflowEnvironment.cpp | 5 +- .../FlowSensitive/DataflowEnvironmentTest.cpp | 50 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 525ab188b01b8aa..5a37fa0f02f5d21 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -300,9 +300,10 @@ static void insertIfFunction(const Decl &D, } static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { - if (!C.getMethodDecl()) + const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(C.getCalleeDecl()); + if (!MethodDecl) return nullptr; - auto *Body = dyn_cast_or_null<CompoundStmt>(C.getMethodDecl()->getBody()); + auto *Body = dyn_cast_or_null<CompoundStmt>(MethodDecl->getBody()); if (!Body || Body->size() != 1) return nullptr; if (auto *RS = dyn_cast<ReturnStmt>(*Body->body_begin())) diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index ff6cbec5d20b744..55fb6549621737a 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -306,6 +306,56 @@ TEST_F(EnvironmentTest, InitGlobalVarsConstructor) { EXPECT_THAT(Env.getValue(*Var), NotNull()); } +// Pointers to Members are a tricky case of accessor calls, complicated further +// when using templates where the pointer to the member is a template argument. +// This is a repro of a failure case seen in the wild. +TEST_F(EnvironmentTest, + ModelMemberForAccessorUsingMethodPointerThroughTemplate) { + using namespace ast_matchers; + + std::string Code = R"cc( + struct S { + int accessor() {return member;} + + int member = 0; + }; + + template <auto method> + int Target(S* S) { + return (S->*method)(); + } + + // We want to analyze the instantiation of Target for the accessor. + int Instantiator () {S S; return Target<&S::accessor>(&S); } + )cc"; + + auto Unit = + // C++17 for the simplifying use of auto in the template declaration. + tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"}); + auto &Context = Unit->getASTContext(); + + ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); + + auto Results = match( + decl(anyOf(functionDecl(hasName("Target"), isTemplateInstantiation()) + .bind("target"), + fieldDecl(hasName("member")).bind("member"), + recordDecl(hasName("S")).bind("struct"))), + Context); + const auto *Fun = selectFirst<FunctionDecl>("target", Results); + const auto *Struct = selectFirst<RecordDecl>("struct", Results); + const auto *Member = selectFirst<FieldDecl>("member", Results); + ASSERT_THAT(Fun, NotNull()); + ASSERT_THAT(Struct, NotNull()); + ASSERT_THAT(Member, NotNull()); + + // Verify that `member` is modeled for `S` when we analyze + // `Target<&S::accessor>`. + Environment Env(DAContext, *Fun); + EXPECT_THAT(DAContext.getModeledFields(QualType(Struct->getTypeForDecl(), 0)), + Contains(Member)); +} + TEST_F(EnvironmentTest, RefreshRecordValue) { using namespace ast_matchers; >From 120bdd51496dd69c601181bccae072effb547920 Mon Sep 17 00:00:00 2001 From: Samira Bazuzi <baz...@google.com> Date: Fri, 1 Dec 2023 10:33:54 -0500 Subject: [PATCH 2/4] Add missing using declaration to test. And add comment. --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp | 1 + .../unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 5a37fa0f02f5d21..0b962bff4c183bf 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -300,6 +300,7 @@ static void insertIfFunction(const Decl &D, } static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { + // Use getCalleeDecl instead of getMethodDecl in order to handle pointer-to-member calls. const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(C.getCalleeDecl()); if (!MethodDecl) return nullptr; diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index 55fb6549621737a..abebd362bec471f 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -27,6 +27,7 @@ using namespace dataflow; using ::clang::dataflow::test::getFieldValue; using ::testing::IsNull; using ::testing::NotNull; +using ::testing::Contains; class EnvironmentTest : public ::testing::Test { protected: >From 8de475f20461a3e45fa3807bdae6315d90445ae4 Mon Sep 17 00:00:00 2001 From: Samira Bazuzi <baz...@google.com> Date: Fri, 1 Dec 2023 10:50:18 -0500 Subject: [PATCH 3/4] Include the clang-format changes. --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 0b962bff4c183bf..bb43d179a0a070e 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -300,7 +300,8 @@ static void insertIfFunction(const Decl &D, } static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { - // Use getCalleeDecl instead of getMethodDecl in order to handle pointer-to-member calls. + // Use getCalleeDecl instead of getMethodDecl in order to handle + // pointer-to-member calls. const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(C.getCalleeDecl()); if (!MethodDecl) return nullptr; >From 4c1220a6f3528422abde72fff26a86602195be6a Mon Sep 17 00:00:00 2001 From: Samira Bazuzi <baz...@google.com> Date: Fri, 1 Dec 2023 10:55:07 -0500 Subject: [PATCH 4/4] And include clang-format changes from a previous commit. I will eventually get used to not amending and clang-format only touching the modified files. --- .../Analysis/FlowSensitive/DataflowEnvironmentTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp index abebd362bec471f..0e7738329022dcb 100644 --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -25,9 +25,9 @@ namespace { using namespace clang; using namespace dataflow; using ::clang::dataflow::test::getFieldValue; +using ::testing::Contains; using ::testing::IsNull; using ::testing::NotNull; -using ::testing::Contains; class EnvironmentTest : public ::testing::Test { protected: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits