[clang] 4aacafd - [clang][ASTVisitor] Visit `HoldingVar` from `BindingDecl`. (#117858)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 12 08:02:03 PST 2024
Author: Clement Courbet
Date: 2024-12-12T17:01:59+01:00
New Revision: 4aacafd49b74dc168e0d99018b4c8289ce9c923e
URL: https://github.com/llvm/llvm-project/commit/4aacafd49b74dc168e0d99018b4c8289ce9c923e
DIFF: https://github.com/llvm/llvm-project/commit/4aacafd49b74dc168e0d99018b4c8289ce9c923e.diff
LOG: [clang][ASTVisitor] Visit `HoldingVar` from `BindingDecl`. (#117858)
Tuple-like types introduce `VarDecl`s in the AST for their "holding
vars", but AST visitors do not visit those. As a result the `VarDecl`
for the holding var is orphaned when trying to retreive its parents.
Fix a `FlowSensitive` test that assumes that only a `BindingDecl` is
introduced with the given name (the matcher now can also reach the
`VarDecl` for the holding var).
Added:
Modified:
clang/include/clang/AST/RecursiveASTVisitor.h
clang/unittests/AST/ASTContextParentMapTest.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 33363072c716f2..5d5c91ff91d553 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2151,8 +2151,11 @@ DEF_TRAVERSE_DECL(DecompositionDecl, {
})
DEF_TRAVERSE_DECL(BindingDecl, {
- if (getDerived().shouldVisitImplicitCode())
+ if (getDerived().shouldVisitImplicitCode()) {
TRY_TO(TraverseStmt(D->getBinding()));
+ if (const auto HoldingVar = D->getHoldingVar())
+ TRY_TO(TraverseDecl(HoldingVar));
+ }
})
DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
diff --git a/clang/unittests/AST/ASTContextParentMapTest.cpp b/clang/unittests/AST/ASTContextParentMapTest.cpp
index 515dfb99e1126d..9af0a46817a25f 100644
--- a/clang/unittests/AST/ASTContextParentMapTest.cpp
+++ b/clang/unittests/AST/ASTContextParentMapTest.cpp
@@ -148,5 +148,54 @@ TEST(GetParents, FriendTypeLoc) {
ElementsAre(DynTypedNode::create(FrA)));
}
+TEST(GetParents, UserDefinedTupleLikeTypes) {
+ MatchVerifier<VarDecl> Verifier;
+ EXPECT_TRUE(Verifier.match(
+ R"(
+namespace std {
+
+using size_t = __typeof(sizeof(int));
+
+template <typename T>
+struct tuple_size;
+
+template <typename T>
+struct tuple_size<T&> : tuple_size<T>{};
+
+template <typename T>
+requires requires { tuple_size<T>::value; }
+struct tuple_size<const T> : tuple_size<T>{};
+
+
+template<size_t i, typename T>
+struct tuple_element;
+
+
+} // namespace std
+
+struct Decomposable {};
+
+template<> struct std::tuple_size<Decomposable> {
+ static constexpr size_t value = 2;
+};
+
+template<std::size_t i> struct std::tuple_element<i, Decomposable> {
+ using type = int;
+};
+
+template<std::size_t i> struct std::tuple_element<i, const Decomposable> {
+ using type = const int;
+};
+
+template<std::size_t i>
+const int& get(const Decomposable& d);
+
+void F(const Decomposable& d) {
+ const auto& [x, y] = d;
+}
+)",
+ varDecl(hasName("x"), hasAncestor(decompositionDecl())), Lang_CXX20));
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 39e7001393e5e9..0f731f4532535e 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -25,6 +25,7 @@
#include "gtest/gtest.h"
#include <optional>
#include <string>
+#include <string_view>
#include <utility>
namespace clang {
@@ -143,6 +144,15 @@ const Formula &getFormula(const ValueDecl &D, const Environment &Env) {
return cast<BoolValue>(Env.getValue(D))->formula();
}
+const BindingDecl *findBindingDecl(ASTContext &ASTCtx, std::string_view Name) {
+ using ast_matchers::bindingDecl;
+ using ast_matchers::hasName;
+ auto TargetNodes =
+ ast_matchers::match(bindingDecl(hasName(Name)).bind("v"), ASTCtx);
+ assert(TargetNodes.size() == 1 && "Name must be unique");
+ return ast_matchers::selectFirst<BindingDecl>("v", TargetNodes);
+}
+
TEST(TransferTest, CNotSupported) {
TestInputs Inputs("void target() {}");
Inputs.Language = TestLanguage::Lang_C89;
@@ -5515,10 +5525,10 @@ TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
- const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
+ const ValueDecl *BoundFooDecl = findBindingDecl(ASTCtx, "BoundFoo");
ASSERT_THAT(BoundFooDecl, NotNull());
- const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
+ const ValueDecl *BoundBarDecl = findBindingDecl(ASTCtx, "BoundBar");
ASSERT_THAT(BoundBarDecl, NotNull());
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
@@ -5596,10 +5606,10 @@ TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
- const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
+ const ValueDecl *BoundFooDecl = findBindingDecl(ASTCtx, "BoundFoo");
ASSERT_THAT(BoundFooDecl, NotNull());
- const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
+ const ValueDecl *BoundBarDecl = findBindingDecl(ASTCtx, "BoundBar");
ASSERT_THAT(BoundBarDecl, NotNull());
const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
More information about the cfe-commits
mailing list