[PATCH] D63149: Added AST matcher for ignoring elidable constructors
This revision was automatically updated to reflect the committed changes. Closed by commit rL363262: Added AST matcher for ignoring elidable constructors (authored by gribozavr, committed by ). Herald added a project: LLVM. Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D63149?vs=204447=204522#toc Repository: rL LLVM CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 Files: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.h Index: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp === --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp @@ -320,6 +320,7 @@ REGISTER_MATCHER(hasUnqualifiedDesugaredType); REGISTER_MATCHER(hasValueType); REGISTER_MATCHER(ifStmt); + REGISTER_MATCHER(ignoringElidableConstructorCall); REGISTER_MATCHER(ignoringImpCasts); REGISTER_MATCHER(ignoringImplicit); REGISTER_MATCHER(ignoringParenCasts); Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), + exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())), + LanguageMode::Cxx11OrLater)); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher = expr(ignoringElidableConstructorCall(declRefExpr())); + EXPECT_TRUE(matches("struct H {};" + "H f() {" + " H g;" + " return g;" + "}", + matcher, LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(notMatches("struct H {};" + "H f() {" + " return H();" + "}", + matcher, LanguageMode::Cxx11OrLater)); +} + +TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) { + EXPECT_TRUE(matches("struct H {};" + "void f() {" + " H D;" + "}", + varDecl(hasInitializer( + ignoringElidableConstructorCall(cxxConstructExpr(, + LanguageMode::Cxx11OrLater)); +} + +TEST(Matcher, IgnoresElidableDoesNotPreventMatches) { + EXPECT_TRUE(matches("void f() {" + " int D = 10;" + "}", + expr(ignoringElidableConstructorCall(integerLiteral())), + LanguageMode::Cxx11OrLater)); +} + TEST(Matcher, BindTheSameNameInAlternatives) { StatementMatcher matcher = anyOf( binaryOperator(hasOperatorName("+"), @@ -914,10 +982,10 @@ varDecl(hasName("foo"), isConstexpr(; EXPECT_TRUE(matches("constexpr int bar();", functionDecl(hasName("bar"), isConstexpr(; - EXPECT_TRUE(matchesConditionally("void baz() { if constexpr(1 > 0) {} }", - ifStmt(isConstexpr()), true, "-std=c++17")); - EXPECT_TRUE(matchesConditionally("void baz() { if (1 > 0) {} }", - ifStmt(isConstexpr()), false, "-std=c++17")); + EXPECT_TRUE(matches("void baz() { if constexpr(1 > 0) {} }", + ifStmt(isConstexpr()), LanguageMode::Cxx17OrLater)); + EXPECT_TRUE(notMatches("void baz() { if (1 > 0) {} }", ifStmt(isConstexpr()), +
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom marked an inline comment as done. jvikstrom added inline comments. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:153 + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } hokein wrote: > nit: add a llvm_unreachable for `default`. But the switch covers all enum values so that would give warnings Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
hokein accepted this revision. hokein added a comment. This revision is now accepted and ready to land. thanks, looks good to me. I'll commit for you. @gribozavr do you want to take another look on the patch? Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:153 + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } hokein wrote: > nit: add a llvm_unreachable for `default`. this is not done? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204447. jvikstrom marked 3 inline comments as done. jvikstrom added a comment. - Removed unnecessary return 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -57,6 +57,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode { + Cxx11, + Cxx14, + Cxx17, + Cxx2a, + Cxx11OrLater, + Cxx14OrLater, + Cxx17OrLater, + Cxx2aOrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +127,71 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModes; + switch (Mode) { + case LanguageMode::Cxx11: + case LanguageMode::Cxx14: + case LanguageMode::Cxx17: + case LanguageMode::Cxx2a: +LangModes = {Mode}; +break; + case LanguageMode::Cxx11OrLater: +LangModes = {LanguageMode::Cxx11, LanguageMode::Cxx14, LanguageMode::Cxx17, + LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx14OrLater: +LangModes = {LanguageMode::Cxx14, LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx17OrLater: +LangModes = {LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } + + for (auto Mode : LangModes) { +std::string LangModeArg; +switch (Mode) { +case LanguageMode::Cxx11: + LangModeArg = "-std=c++11"; + break; +case LanguageMode::Cxx14: + LangModeArg = "-std=c++14"; + break; +case LanguageMode::Cxx17: + LangModeArg = "-std=c++17"; + break; +case LanguageMode::Cxx2a: + LangModeArg = "-std=c++2a"; + break; +default: + llvm_unreachable("Invalid language mode"); +} + +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) + return Result; + } + + return testing::AssertionSuccess(); +} + +template +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, true, Modes); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), + exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())), + LanguageMode::Cxx11OrLater)); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher =
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
hokein added a comment. looks most good to me, a few nits. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6488 + } + return InnerMatcher.matches(*CtorExpr, Finder, Builder); +} This `return` statement is not needed. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:16 #include "gtest/gtest.h" +#include looks like the `include` is not used? Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:153 + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } nit: add a llvm_unreachable for `default`. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:177 +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; nit: no `{}` needed for a single-statement body. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204443. jvikstrom marked an inline comment as done. jvikstrom added a comment. - Removed dependency on unordered map 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -57,6 +57,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode { + Cxx11, + Cxx14, + Cxx17, + Cxx2a, + Cxx11OrLater, + Cxx14OrLater, + Cxx17OrLater, + Cxx2aOrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +127,72 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModes; + switch (Mode) { + case LanguageMode::Cxx11: + case LanguageMode::Cxx14: + case LanguageMode::Cxx17: + case LanguageMode::Cxx2a: +LangModes = {Mode}; +break; + case LanguageMode::Cxx11OrLater: +LangModes = {LanguageMode::Cxx11, LanguageMode::Cxx14, LanguageMode::Cxx17, + LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx14OrLater: +LangModes = {LanguageMode::Cxx14, LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx17OrLater: +LangModes = {LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } + + for (auto Mode : LangModes) { +std::string LangModeArg; +switch (Mode) { +case LanguageMode::Cxx11: + LangModeArg = "-std=c++11"; + break; +case LanguageMode::Cxx14: + LangModeArg = "-std=c++14"; + break; +case LanguageMode::Cxx17: + LangModeArg = "-std=c++17"; + break; +case LanguageMode::Cxx2a: + LangModeArg = "-std=c++2a"; + break; +default: + llvm_unreachable("Invalid language mode"); +} + +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), + exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())), + LanguageMode::Cxx11OrLater)); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher =
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204442. jvikstrom added a comment. - Updated outdated docs 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -13,6 +13,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" +#include namespace clang { namespace ast_matchers { @@ -57,6 +58,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode { + Cxx11, + Cxx14, + Cxx17, + Cxx2a, + Cxx11OrLater, + Cxx14OrLater, + Cxx17OrLater, + Cxx2aOrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +128,72 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModes; + switch (Mode) { + case LanguageMode::Cxx11: + case LanguageMode::Cxx14: + case LanguageMode::Cxx17: + case LanguageMode::Cxx2a: +LangModes = {Mode}; +break; + case LanguageMode::Cxx11OrLater: +LangModes = {LanguageMode::Cxx11, LanguageMode::Cxx14, LanguageMode::Cxx17, + LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx14OrLater: +LangModes = {LanguageMode::Cxx14, LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx17OrLater: +LangModes = {LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } + + for (auto Mode : LangModes) { +std::string LangModeArg; +switch (Mode) { +case LanguageMode::Cxx11: + LangModeArg = "-std=c++11"; + break; +case LanguageMode::Cxx14: + LangModeArg = "-std=c++14"; + break; +case LanguageMode::Cxx17: + LangModeArg = "-std=c++17"; + break; +case LanguageMode::Cxx2a: + LangModeArg = "-std=c++2a"; + break; +default: + llvm_unreachable("Invalid language mode"); +} + +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), + exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())), +
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204437. jvikstrom marked an inline comment as done. jvikstrom added a comment. - Added default to switch for language modes 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -13,6 +13,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" +#include namespace clang { namespace ast_matchers { @@ -57,6 +58,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode { + Cxx11, + Cxx14, + Cxx17, + Cxx2a, + Cxx11OrLater, + Cxx14OrLater, + Cxx17OrLater, + Cxx2aOrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +128,72 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModes; + switch (Mode) { + case LanguageMode::Cxx11: + case LanguageMode::Cxx14: + case LanguageMode::Cxx17: + case LanguageMode::Cxx2a: +LangModes = {Mode}; +break; + case LanguageMode::Cxx11OrLater: +LangModes = {LanguageMode::Cxx11, LanguageMode::Cxx14, LanguageMode::Cxx17, + LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx14OrLater: +LangModes = {LanguageMode::Cxx14, LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx17OrLater: +LangModes = {LanguageMode::Cxx17, LanguageMode::Cxx2a}; +break; + case LanguageMode::Cxx2aOrLater: +LangModes = {LanguageMode::Cxx2a}; + } + + for (auto Mode : LangModes) { +std::string LangModeArg; +switch (Mode) { +case LanguageMode::Cxx11: + LangModeArg = "-std=c++11"; + break; +case LanguageMode::Cxx14: + LangModeArg = "-std=c++14"; + break; +case LanguageMode::Cxx17: + LangModeArg = "-std=c++17"; + break; +case LanguageMode::Cxx2a: + LangModeArg = "-std=c++2a"; + break; +default: + llvm_unreachable("Invalid language mode"); +} + +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::Cxx11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::Cxx11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), +
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
gribozavr added inline comments. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:69 + CXX17OrLater, + CXX2AOrLater +}; Cxx2aOrLater? (no need to uppercase things) Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:159 +switch (Mode) { +case LanguageMode::CXX11OrLater: +case LanguageMode::CXX11: The "orlater" variants should not appear here, please use "default: llvm_unreachable()". Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204282. jvikstrom marked 7 inline comments as done. jvikstrom added a comment. - Using switch for choosing language standard 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -13,6 +13,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" +#include namespace clang { namespace ast_matchers { @@ -57,6 +58,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode { + CXX11, + CXX14, + CXX17, + CXX2A, + CXX11OrLater, + CXX14OrLater, + CXX17OrLater, + CXX2AOrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +128,73 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModes; + switch (Mode) { + case LanguageMode::CXX11: + case LanguageMode::CXX14: + case LanguageMode::CXX17: + case LanguageMode::CXX2A: +LangModes = {Mode}; +break; + case LanguageMode::CXX11OrLater: +LangModes = {LanguageMode::CXX11, LanguageMode::CXX14, LanguageMode::CXX17, + LanguageMode::CXX2A}; +break; + case LanguageMode::CXX14OrLater: +LangModes = {LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX2A}; +break; + case LanguageMode::CXX17OrLater: +LangModes = {LanguageMode::CXX17, LanguageMode::CXX2A}; +break; + case LanguageMode::CXX2AOrLater: +LangModes = {LanguageMode::CXX2A}; + } + + for (auto Mode : LangModes) { +std::string LangModeArg; +switch (Mode) { +case LanguageMode::CXX11OrLater: +case LanguageMode::CXX11: + LangModeArg = "-std=c++11"; + break; +case LanguageMode::CXX14OrLater: +case LanguageMode::CXX14: + LangModeArg = "-std=c++14"; + break; +case LanguageMode::CXX17OrLater: +case LanguageMode::CXX17: + LangModeArg = "-std=c++17"; + break; +case LanguageMode::CXX2AOrLater: +case LanguageMode::CXX2A: + LangModeArg = "-std=c++2a"; +} + +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,74 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()), + LanguageMode::CXX11OrLater)); + EXPECT_TRUE( + matches("struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}", + cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()), + LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches( + "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}", + varDecl(hasInitializer(anyOf( +
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
gribozavr added inline comments. Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:600 + EXPECT_TRUE(matches(code2, matcher2, LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches(code3, matcher3, LanguageMode::CXX11OrLater)); +} Please inline the variables that are used once. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:61 +enum class LanguageMode : int { + CXX11 = 0, + CXX14 = 1, Please drop the explicit values. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:64 + CXX17 = 2, + CXX20 = 3, + CXX11OrLater, 2a Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:68 + CXX17OrLater, + CXX20OrLater +}; "2a" (we don't know the year yet) Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:144 + case LanguageMode::CXX11OrLater: +LangModes = {LanguageMode::CXX11, LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX20}; +break; 80 columns. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:154 +LangModes = {LanguageMode::CXX20}; + }; + No need for semicolon. Comment at: clang/unittests/ASTMatchers/ASTMatchersTest.h:157 + for (auto Mode : LangModes) { +auto LangModeArg = LangModeStrings[static_cast(Mode)]; +auto Result = I'd say it is too clever, and suggest to write an explicit switch. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204277. jvikstrom marked 10 inline comments as done. jvikstrom added a comment. - Fixed wrong formatting in test 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -57,6 +57,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode : int { + CXX11 = 0, + CXX14 = 1, + CXX17 = 2, + CXX20 = 3, + CXX11OrLater, + CXX14OrLater, + CXX17OrLater, + CXX20OrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +127,56 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModeStrings{"-std=c++11", "-std=c++14", + "-std=c++17", "-std=c++20"}; + std::vector LangModes; + switch (Mode) { + case LanguageMode::CXX11: + case LanguageMode::CXX14: + case LanguageMode::CXX17: + case LanguageMode::CXX20: +LangModes = {Mode}; +break; + case LanguageMode::CXX11OrLater: +LangModes = {LanguageMode::CXX11, LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX14OrLater: +LangModes = {LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX17OrLater: +LangModes = {LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX20OrLater: +LangModes = {LanguageMode::CXX20}; + }; + + for (auto Mode : LangModes) { +auto LangModeArg = LangModeStrings[static_cast(Mode)]; +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,73 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + auto matcher1 = cxxOperatorCallExpr(hasArgument( + 1, + callExpr(hasArgument(0, ignoringElidableConstructorCall(callExpr()); + auto matcher2 = cxxOperatorCallExpr( + hasArgument(1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()); + auto matcher3 = varDecl(hasInitializer(anyOf( + ignoringElidableConstructorCall(callExpr()), + exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())); + + auto code1 = "struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}"; + auto code2 = "struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}"; + auto code3 = "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}"; + + EXPECT_TRUE(matches(code1, matcher1, LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches(code2, matcher2, LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches(code3, matcher3, LanguageMode::CXX11OrLater)); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher = expr(ignoringElidableConstructorCall(declRefExpr())); + EXPECT_TRUE(matches("struct H {};" + "H f() {" + " H g;" + " return g;" + "}",
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204269. jvikstrom marked 3 inline comments as done. jvikstrom added a comment. - Added match conditionally overload to control in what language standard a match should run in 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 clang/unittests/ASTMatchers/ASTMatchersTest.h Index: clang/unittests/ASTMatchers/ASTMatchersTest.h === --- clang/unittests/ASTMatchers/ASTMatchersTest.h +++ clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -57,6 +57,17 @@ const std::unique_ptr FindResultReviewer; }; +enum class LanguageMode : int { + CXX11 = 0, + CXX14 = 1, + CXX17 = 2, + CXX20 = 3, + CXX11OrLater, + CXX14OrLater, + CXX17OrLater, + CXX20OrLater +}; + template testing::AssertionResult matchesConditionally( const std::string , const T , bool ExpectMatch, @@ -116,14 +127,56 @@ } template -testing::AssertionResult matches(const std::string , const T ) { - return matchesConditionally(Code, AMatcher, true, "-std=c++11"); +testing::AssertionResult +matchesConditionally(const std::string , const T , + bool ExpectMatch, const LanguageMode ) { + std::vector LangModeStrings{"-std=c++11", "-std=c++14", + "-std=c++17", "-std=c++20"}; + std::vector LangModes; + switch (Mode) { + case LanguageMode::CXX11: + case LanguageMode::CXX14: + case LanguageMode::CXX17: + case LanguageMode::CXX20: +LangModes = {Mode}; +break; + case LanguageMode::CXX11OrLater: +LangModes = {LanguageMode::CXX11, LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX14OrLater: +LangModes = {LanguageMode::CXX14, LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX17OrLater: +LangModes = {LanguageMode::CXX17, LanguageMode::CXX20}; +break; + case LanguageMode::CXX20OrLater: +LangModes = {LanguageMode::CXX20}; + }; + + for (auto Mode : LangModes) { +auto LangModeArg = LangModeStrings[static_cast(Mode)]; +auto Result = +matchesConditionally(Code, AMatcher, ExpectMatch, LangModeArg); +if (!Result) { + return Result; +} + } + + return testing::AssertionSuccess(); } template -testing::AssertionResult notMatches(const std::string , -const T ) { - return matchesConditionally(Code, AMatcher, false, "-std=c++11"); +testing::AssertionResult +matches(const std::string , const T , +const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, true, Modes); +} + +template +testing::AssertionResult +notMatches(const std::string , const T , + const LanguageMode = LanguageMode::CXX11) { + return matchesConditionally(Code, AMatcher, false, Modes); } template Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -566,6 +566,76 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + auto matcher1 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableConstructorCall(callExpr()); + auto matcher2 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableConstructorCall( + integerLiteral()); + auto matcher3 = + varDecl(hasInitializer( +anyOf( +ignoringElidableConstructorCall(callExpr()), +exprWithCleanups(has(ignoringElidableConstructorCall(callExpr( +))); + + auto code1 = "struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(B(1));" + "}"; + auto code2 = "struct H {};" + "template H B(T A);" + "void f() {" + " H D1;" + " D1 = B(1);" + "}"; + auto code3 = "struct H {};" + "H G();" + "void f() {" + " H D = G();" + "}"; + + EXPECT_TRUE(matches(code1, matcher1, LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches(code2, matcher2, LanguageMode::CXX11OrLater)); + EXPECT_TRUE(matches(code3, matcher3, LanguageMode::CXX11OrLater)); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher = expr(ignoringElidableConstructorCall(declRefExpr())); + EXPECT_TRUE(matches("struct H{};" + "H f() {" +
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204245. jvikstrom added a comment. - Using CamelCase and also renamed ignoringElidableMoveConstructorCall to ignoringElidableConstructorCall 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,81 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + auto matcher1 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableMoveConstructorCall(callExpr().bind("c")); + auto matcher2 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableMoveConstructorCall( + integerLiteral().bind("c")); + auto matcher3 = + varDecl(hasInitializer(ignoringElidableMoveConstructorCall(callExpr(; + + auto code1 = "struct H {};" + "template H B(T A);" + "void f(){" + "H D1;" + "D1=B(B(1));" + "}"; + auto code2 = "struct H {};" + "template H B(T A);" + "void f(){" + "H D1;" + "D1=B(1);" + "}"; + auto code3 = "struct H {};" + "H G();" + "void f(){" + "H D = G();" + "}"; + + 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")); + + EXPECT_TRUE(matchesConditionally(code3, matcher3, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code3, matcher3, 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,56 @@ return false; } +/// Matches expressions that match InnerMatcher that are possibly wrapped in an +/// elidable constructor. +/// +/// 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 AST in C++14 and earlier. Therefore, to write a
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom updated this revision to Diff 204244. jvikstrom marked an inline comment as done. jvikstrom added a comment. - Updated example and fixed edge case in ignoringElidableConstructorCall 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,81 @@ llvm::make_unique>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + auto matcher1 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument( + 0, ignoringElidableMoveConstructorCall(callExpr().bind("c")); + auto matcher2 = cxxOperatorCallExpr(hasArgument( + 1, callExpr(hasArgument(0, ignoringElidableMoveConstructorCall( + integerLiteral().bind("c")); + auto matcher3 = + varDecl(hasInitializer(ignoringElidableMoveConstructorCall(callExpr(; + + auto code1 = "struct H {};" + "template H B(T A);" + "void f(){" + "H D1;" + "D1=B(B(1));" + "}"; + auto code2 = "struct H {};" + "template H B(T A);" + "void f(){" + "H D1;" + "D1=B(1);" + "}"; + auto code3 = "struct H {};" + "H G();" + "void f(){" + "H D = G();" + "}"; + + 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")); + + EXPECT_TRUE(matchesConditionally(code3, matcher3, true, "-std=c++14")); + EXPECT_TRUE(matchesConditionally(code3, matcher3, 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,56 @@ return false; } +/// Matches expressions that match InnerMatcher that are possibly wrapped in an +/// elidable constructor. +/// +/// 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 AST in C++14 and earlier. Therefore, to
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
hokein added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6477 +/// matches ``D1 = B(B(1))`` +AST_MATCHER_P(Expr, ignoringElidableMoveConstructorCall, + ast_matchers::internal::Matcher, InnerMatcher) { Is the matcher only strict to **move** constructor? looks like the matcher implementation is for general constructors, just `ignoringElidableConstructorCall`? we may have elidable copy constructor. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6479 + ast_matchers::internal::Matcher, InnerMatcher) { + if (const auto *cxx_construct_expr = dyn_cast()) { +if (cxx_construct_expr->isElidable()) { nit: [LLVM](https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly) uses `CamelCase` style. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6486 + } + return InnerMatcher.matches(*cxx_construct_expr, Finder, Builder); +} I think this return is unnecessary, since we will fall through at line 6489. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
gribozavr added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6455 +/// Matches expressions that match InnerMatcher after any elidable constructor +/// are stripped off. In C++17 copy elidable constructors are no longer being "Matches expressions that match InnerMatcher that are possibly wrapped in an elidable constructor." Then a blank line, and the rest of the explanation. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6458 +/// 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 part of the AST in C++14 and earlier. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6460 +/// 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)``. Therefore, to write a matcher that works in all language modes, the matcher has to skip elidable constructor AST nodes if they appear in the AST. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6467 +/// struct H {}; +/// template H B(T A); +/// void f() { Can this sample be simplified? For example, B does not need to be a template (I think), and f() can be simplified to not call B twice. Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:628 + EXPECT_TRUE(matches( +"void f(){" +"int D = 10;" gribozavr wrote: > Need a space before the open brace, and indentation in the function body (in > every test). Not done? I was talking about the code in the code snippet. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
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>("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 H B(T A);" + "void f(){" + "H D1;" + "D1=B(B(1));" + "}"; + auto code2 = "struct H {};" + "template 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 H B(T A); +/// void f() { +/// H D1; +/// D1 = B(B(1)); +/// } +/// \endcode +/// +///
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
gribozavr added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6455 +/// Matches expressions that match InnerMatcher after any elidable constructor are stripped off. +/// 80 columns Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6455 +/// Matches expressions that match InnerMatcher after any elidable constructor are stripped off. +/// gribozavr wrote: > 80 columns It would help if you described why a user would want to skip the elidable constructor using this matcher rather than hardcoding the presence of such an AST node. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:6457 +/// +/// Example matches the entire D1 = ... (matcher = cxxOperatorCallExpr(hasArgument(1, callExpr(hasArgument(0, ignoringElidableMoveConstructorCall(ignoringParenImpCasts(callExpr( +/// \code I'd suggest to rephrase the example using the "Given:" format (see other comments around), and wrap the code to 80 columns. Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:575 + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct H {};" Can you run these tests in both C++14 and C++17 modes? Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:628 + EXPECT_TRUE(matches( +"void f(){" +"int D = 10;" Need a space before the open brace, and indentation in the function body (in every test). Comment at: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp:631 +"}" + , matcher)); +} Please clang-format. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D63149/new/ https://reviews.llvm.org/D63149 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D63149: Added AST matcher for ignoring elidable constructors
jvikstrom created this revision. jvikstrom added reviewers: hokein, gribozavr. Herald added a project: clang. Herald added a subscriber: cfe-commits. Added AST matcher for ignoring elidable move constructors Repository: rG LLVM Github Monorepo 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>("x"))); } +TEST(Matcher, IgnoresElidableConstructors) { + StatementMatcher matcher = cxxOperatorCallExpr( +hasArgument(1, callExpr(hasArgument(0, +ignoringElidableMoveConstructorCall( + ignoringParenImpCasts(expr().bind("c"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct H {};" +"template H B(T A);" +"void f(){" +"H D1;" +"D1=B(B(1));" +"}" +, matcher, llvm::make_unique>("c"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct H {};" +"template H B(T A);" +"void f(){" +"H D1;" +"D1=B(1);" +"}" +, matcher, llvm::make_unique>("c"))); +} + +TEST(Matcher, IgnoresElidableInReturn) { + auto matcher = expr(ignoringElidableMoveConstructorCall(declRefExpr())); + + EXPECT_TRUE(matches( +"struct H{};" +"H f(){" +"H g;" +"return g;" +"}" +, matcher)); + + EXPECT_FALSE(matches( +"struct H{};" +"H f(){" +"return H();" +"}" +, matcher + )); +} + +TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) { + auto matcher = varDecl(hasInitializer(ignoringElidableMoveConstructorCall(cxxConstructExpr(; + EXPECT_TRUE(matches( +"struct H {};" +"void f(){" +"H D;" +"}" + , matcher)); + +}; + +TEST(Matcher, IgnoresElidableDoesNotPreventMatches) { + auto matcher = expr(ignoringElidableMoveConstructorCall(integerLiteral())); + EXPECT_TRUE(matches( +"void f(){" +"int D = 10;" +"}" + , matcher)); +} + 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,31 @@ return false; } +/// 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( +/// \code +/// struct H {}; +/// template H B(T A); +/// void f() { +/// H D1; +/// D1 = B(B(1)); +/// } +/// \endcode +AST_MATCHER_P(Expr, ignoringElidableMoveConstructorCall, + ast_matchers::internal::Matcher, InnerMatcher) { + if (const auto* cxx_construct_expr = dyn_cast()) { +if (cxx_construct_expr->isElidable()) { + if (const auto* materialize_temp = dyn_cast( + cxx_construct_expr->getArg(0))) { +return InnerMatcher.matches(*materialize_temp, 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 @@ +Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>ExprignoringElidableMoveConstructorCallast_matchers::Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Expr.html;>Expr InnerMatcher +Matches expressions that match InnerMatcher after any elidable constructor are stripped off. + +Example matches the entire D1 = ...