Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -552,6 +552,28 @@ Stmt, CXXBindTemporaryExpr> bindTemporaryExpr; +/// \brief Matches nodes where temporaries are materialized. +/// +/// Example: Given +/// \code +/// struct T {void func()}; +/// T f(); +/// void g(T); +/// \endcode +/// materializeTempExpr() 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> materializeTempExpr; + /// \brief Matches new expressions. /// /// Given Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1296,6 +1296,41 @@ TempExpression)); } +TEST(MaterializeTempExpr, MatchesTemporary) { + std::string ClassString = + "class string { public: string(); int length(); }; "; + + EXPECT_TRUE( + matches(ClassString + + "string GetStringByValue();" + "void FunctionTakesString(string s);" + "void run() { FunctionTakesString(GetStringByValue()); }", + materializeTempExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string* GetStringPointer(); " + "void FunctionTakesStringPtr(string* s);" + "void run() {" + " string* s = GetStringPointer();" + " FunctionTakesStringPtr(GetStringPointer());" + " FunctionTakesStringPtr(s);" + "}", + materializeTempExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string GetStringByValue();" + "void run() { int k = GetStringByValue().length(); }", + materializeTempExpr())); + + EXPECT_TRUE( + notMatches(ClassString + + "string GetStringByValue();" + "void run() { GetStringByValue(); }", + materializeTempExpr())); +} + TEST(ConstructorDeclaration, SimpleCase) { EXPECT_TRUE(matches("class Foo { Foo(int i); };", constructorDecl(ofClass(hasName("Foo")))));