Index: clang/include/clang/AST/ASTNodeTraverser.h =================================================================== --- clang/include/clang/AST/ASTNodeTraverser.h +++ clang/include/clang/AST/ASTNodeTraverser.h @@ -467,6 +467,10 @@ void VisitBindingDecl(const BindingDecl *D) { if (Traversal == TK_IgnoreUnlessSpelledInSource) return; + + if (const auto *V = D->getHoldingVar()) + Visit(V); + if (const auto *E = D->getBinding()) Visit(E); } Index: clang/unittests/AST/ASTTraverserTest.cpp =================================================================== --- clang/unittests/AST/ASTTraverserTest.cpp +++ clang/unittests/AST/ASTTraverserTest.cpp @@ -1157,6 +1157,58 @@ f = 42; } +typedef __typeof(sizeof(int)) size_t; + +struct Pair +{ + int x, y; +}; + +// Note: these utilities are required to force binding to tuple like structure +namespace std +{ + template + struct tuple_size + { + }; + + template <> + struct tuple_size + { + static constexpr size_t value = 2; + }; + + template + struct tuple_element + { + using type = int; + }; + +}; + +template +int &&get(Pair &&p); + +template <> +int &&get<0>(Pair &&p) +{ + return (int &&)p.x; +} + +template <> +int &&get<1>(Pair &&p) +{ + return (int &&)p.y; +} + +void decompTuple() +{ + Pair p{1, 2}; + auto [a, b] = p; + + a = 3; +} + )cpp", {"-std=c++20"}); @@ -1492,6 +1544,48 @@ |-BindingDecl 'f' |-BindingDecl 's' `-BindingDecl 't' +)cpp"); + } + + { + auto FN = ast_matchers::match( + functionDecl(hasName("decompTuple"), + hasDescendant(decompositionDecl().bind("decomp"))), + AST2->getASTContext()); + EXPECT_EQ(FN.size(), 1u); + + EXPECT_EQ( + dumpASTString(TK_AsIs, FN[0].getNodeAs("decomp")), + R"cpp( +DecompositionDecl '' +|-CXXConstructExpr +| `-ImplicitCastExpr +| `-DeclRefExpr 'p' +|-BindingDecl 'a' +| |-VarDecl 'a' +| | `-CallExpr +| | |-ImplicitCastExpr +| | | `-DeclRefExpr 'get' +| | `-ImplicitCastExpr +| | `-DeclRefExpr '' +| `-DeclRefExpr 'a' +`-BindingDecl 'b' + |-VarDecl 'b' + | `-CallExpr + | |-ImplicitCastExpr + | | `-DeclRefExpr 'get' + | `-ImplicitCastExpr + | `-DeclRefExpr '' + `-DeclRefExpr 'b' +)cpp"); + + EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, + FN[0].getNodeAs("decomp")), + R"cpp( +DecompositionDecl '' +|-DeclRefExpr 'p' +|-BindingDecl 'a' +`-BindingDecl 'b' )cpp"); } }