diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 736e1dfcabcf..c91b2a249029 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -924,6 +924,19 @@ in +
Matches C++ initializer list expressions. + +Given + std::vector<int> a({ 1, 2, 3 }); + std::vector<int> b = { 4, 5 }; + int c[] = { 6, 7 }; + std::pair<int, int> d = { 8, 9 }; +cxxStdInitializerListExpr() + matches "{ 1, 2, 3 }" and "{ 4, 5 }" +
Matches functional cast expressions having N != 1 arguments @@ -1160,7 +1173,7 @@ Example matches [&](){return 5;} Matches nodes where temporaries are materialized. Example: Given - struct T {void func()}; + struct T {void func();}; T f(); void g(T); materializeTemporaryExpr() matches 'f()' in these statements @@ -5233,7 +5246,7 @@ Example matches y in x(y) Matches on the receiver of an ObjectiveC Message expression. Example -matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *"))); +matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *"))); matches the [webView ...] message invocation. NSString *webViewJavaScript = ... UIWebView *webView = ... diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index f11469b8fc20..0ab8d5fe4fc1 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1223,6 +1223,20 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm, InnerMatcher.matches(*SyntForm, Finder, Builder)); } +/// \brief Matches C++ initializer list expressions. +/// +/// Given +/// \code +/// std::vectora({ 1, 2, 3 }); +/// std::vector b = { 4, 5 }; +/// int c[] = { 6, 7 }; +/// std::pair d = { 8, 9 }; +/// \endcode +/// cxxStdInitializerListExpr() +/// matches "{ 1, 2, 3 }" and "{ 4, 5 }" +const internal::VariadicDynCastAllOfMatcher cxxStdInitializerListExpr; + /// \brief Matches implicit initializers of init list expressions. /// /// Given diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 6f935620888f..26743d86f5e7 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -153,6 +153,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(cxxRecordDecl); REGISTER_MATCHER(cxxReinterpretCastExpr); REGISTER_MATCHER(cxxStaticCastExpr); + REGISTER_MATCHER(cxxStdInitializerListExpr); REGISTER_MATCHER(cxxTemporaryObjectExpr); REGISTER_MATCHER(cxxThisExpr); REGISTER_MATCHER(cxxThrowExpr); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 5c29334222df..dfaa441cd764 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1020,6 +1020,29 @@ TEST(InitListExpression, MatchesInitListExpression) { matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42)))); } +TEST(CXXStdInitializerListExpression, MatchesCXXStdInitializerListExpression) { + const std::string code = "namespace std {" + "template class initializer_list {" + " public: initializer_list() noexcept {}" + "};" + "}" + "struct A {" + " A(std::initializer_list ) {}" + "};"; + EXPECT_TRUE(matches(code + "A a{0};", + cxxConstructExpr(has(cxxStdInitializerListExpr()), + hasDeclaration(cxxConstructorDecl( + ofClass(hasName("A"))))))); + EXPECT_TRUE(matches(code + "A a = {0};", + cxxConstructExpr(has(cxxStdInitializerListExpr()), + hasDeclaration(cxxConstructorDecl( + ofClass(hasName("A"))))))); + + EXPECT_TRUE(notMatches("int a[] = { 1, 2 };", cxxStdInitializerListExpr())); + EXPECT_TRUE(notMatches("struct B { int x, y; }; B b = { 5, 6 };", + cxxStdInitializerListExpr())); +} + TEST(UsingDeclaration, MatchesUsingDeclarations) { EXPECT_TRUE(matches("namespace X { int x; } using X::x;", usingDecl()));