diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 2cd409c3e3..25d10a5a40 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -552,6 +552,28 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CXXBindTemporaryExpr> bindTemporaryExpr; +/// \brief Matches nodes where temporaries are materialized. +/// +/// Example: Given +/// \code +/// struct T {void func()}; +/// T f(); +/// void g(T); +/// \endcode +/// materializeTemporaryExpr() matches 'f()' in these statements +/// \code +/// T u(f()); +/// g(f()); +/// \endcode +/// but does not match +/// \code +/// f(); +/// f().func(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + MaterializeTemporaryExpr> materializeTemporaryExpr; + /// \brief Matches new expressions. /// /// Given diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 81f6808208..951bca9a30 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1296,6 +1296,41 @@ TEST(Matcher, BindTemporaryExpression) { TempExpression)); } +TEST(MaterializeTemporaryExpr, MatchesTemporary) { + std::string ClassString = + "class string { public: string(); int length(); }; "; + + EXPECT_TRUE( + matches(ClassString + + "string GetStringByValue();" + "void FunctionTakesString(string s);" + "void run() { FunctionTakesString(GetStringByValue()); }", + materializeTemporaryExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string* GetStringPointer(); " + "void FunctionTakesStringPtr(string* s);" + "void run() {" + " string* s = GetStringPointer();" + " FunctionTakesStringPtr(GetStringPointer());" + " FunctionTakesStringPtr(s);" + "}", + materializeTemporaryExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string GetStringByValue();" + "void run() { int k = GetStringByValue().length(); }", + materializeTemporaryExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string GetStringByValue();" + "void run() { GetStringByValue(); }", + materializeTemporaryExpr())); +} + TEST(ConstructorDeclaration, SimpleCase) { EXPECT_TRUE(matches("class Foo { Foo(int i); };", constructorDecl(ofClass(hasName("Foo")))));