jvikstrom updated this revision to Diff 204229. jvikstrom added a comment. - Made ignoreElidable also ignore materializeTemporaryExpr and reformatted code
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,71 @@ llvm::make_unique<VerifyIdIsBoundTo<CXXMemberCallExpr>>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + StatementMatcher matcher1 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableMoveConstructorCall(callExpr().bind("c")))))); + StatementMatcher matcher2 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableMoveConstructorCall( + integerLiteral().bind("c")))))); + + auto code1 = "struct H {};" + "template<typename T> H B(T A);" + "void f(){" + "H D1;" + "D1=B(B(1));" + "}"; + auto code2 = "struct H {};" + "template<typename T> H B(T A);" + "void f(){" + "H D1;" + "D1=B(1);" + "}"; + + EXPECT_TRUE(matchesConditionally(code1, matcher1, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code1, matcher1, true, "-std=c++17")); + + EXPECT_TRUE(matchesConditionally(code2, matcher2, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code2, matcher2, true, "-std=c++17")); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher = expr(ignoringElidableMoveConstructorCall(declRefExpr())); + auto code1 = "struct H{};" + "H f(){" + "H g;" + "return g;" + "}"; + auto code2 = "struct H{};" + "H f(){" + "return H();" + "}"; + EXPECT_TRUE(matchesConditionally(code1, matcher, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code1, matcher, true, "-std=c++17")); + EXPECT_TRUE(matchesConditionally(code2, matcher, false, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code2, matcher, false, "-std=c++17")); +} + +TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) { + auto matcher = varDecl( + hasInitializer(ignoringElidableMoveConstructorCall(cxxConstructExpr()))); + auto code = "struct H {};" + "void f(){" + "H D;" + "}"; + EXPECT_TRUE(matchesConditionally(code, matcher, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code, matcher, true, "-std=c++17")); +}; + +TEST(Matcher, IgnoresElidableDoesNotPreventMatches) { + auto matcher = expr(ignoringElidableMoveConstructorCall(integerLiteral())); + auto code = "void f(){" + "int D = 10;" + "}"; + EXPECT_TRUE(matchesConditionally(code, matcher, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code, matcher, true, "-std=c++17")); +} + TEST(Matcher, BindTheSameNameInAlternatives) { StatementMatcher matcher = anyOf( binaryOperator(hasOperatorName("+"), Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -320,6 +320,7 @@ REGISTER_MATCHER(hasUnqualifiedDesugaredType); REGISTER_MATCHER(hasValueType); REGISTER_MATCHER(ifStmt); + REGISTER_MATCHER(ignoringElidableMoveConstructorCall); REGISTER_MATCHER(ignoringImpCasts); REGISTER_MATCHER(ignoringImplicit); REGISTER_MATCHER(ignoringParenCasts); Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -6452,6 +6452,43 @@ return false; } +/// Matches expressions that match InnerMatcher after any elidable constructor +/// are stripped off. In C++17 copy elidable constructors are no longer being +/// generated in the AST as it is not permitted by the standard. They are +/// however part of the C++14 AST. This means that there are cases where it is +/// needed to use ``anyOf(cxxConstructorExpr(Inner), Inner)`` to match for both +/// the C++14 and C++17 AST. Instead of doing this, this matcher can be used as +/// ``ignoringElidableMoveConstructorCall(Inner)``. +/// +/// Given +/// +/// \code +/// struct H {}; +/// template<typename T> H B(T A); +/// void f() { +/// H D1; +/// D1 = B(B(1)); +/// } +/// \endcode +/// +/// ``cxxOperatorCallExpr(hasArgument(1, callExpr(hasArgument(0, +/// ignoringElidableMoveConstructorCall(ignoringParenImpCasts(callExpr()))))))`` +/// matches ``D1 = B(B(1))`` +AST_MATCHER_P(Expr, ignoringElidableMoveConstructorCall, + ast_matchers::internal::Matcher<Expr>, InnerMatcher) { + if (const auto *cxx_construct_expr = dyn_cast<CXXConstructExpr>(&Node)) { + if (cxx_construct_expr->isElidable()) { + if (const auto *materialize_temp = dyn_cast<MaterializeTemporaryExpr>( + cxx_construct_expr->getArg(0))) { + return InnerMatcher.matches(*materialize_temp->IgnoreImplicit(), Finder, + Builder); + } + return InnerMatcher.matches(*cxx_construct_expr, Finder, Builder); + } + } + return InnerMatcher.matches(Node, Finder, Builder); +} + //----------------------------------------------------------------------------// // OpenMP handling. //----------------------------------------------------------------------------// Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -5728,6 +5728,19 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('ignoringElidableMoveConstructorCall0')"><a name="ignoringElidableMoveConstructorCall0Anchor">ignoringElidableMoveConstructorCall</a></td><td>ast_matchers::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="ignoringElidableMoveConstructorCall0"><pre>Matches expressions that match InnerMatcher after any elidable constructor are stripped off. + +Example matches the entire D1 = ... (matcher = cxxOperatorCallExpr(hasArgument(1, callExpr(hasArgument(0, ignoringElidableMoveConstructorCall(ignoringParenImpCasts(callExpr()))))))) +struct H {}; +template<typename T> H B(T A); +void f() { + H D1; + D1 = B(B(1)); +} +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('ignoringImpCasts0')"><a name="ignoringImpCasts0Anchor">ignoringImpCasts</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="ignoringImpCasts0"><pre>Matches expressions that match InnerMatcher after any implicit casts are stripped off.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits