diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -3965,6 +3965,44 @@ return false; } +/// Matches the type of a return statement as declared by the enclosing +/// function. +/// +/// Example: returnStmt(hasExpectedReturnType(asString("int *"))) will match +/// return 0; in +/// \code +/// int* foo() { +/// return 0; +/// } +/// \endcode +/// despite the return value being an IntegerLiteral. + +AST_MATCHER_P(ReturnStmt, hasExpectedReturnType, internal::Matcher, + InnerMatcher) { + const auto &Parents = Finder->getASTContext().getParents(Node); + + llvm::SmallVector Stack(Parents.begin(), Parents.end()); + const FunctionDecl* FuncDeclNode; + while (!Stack.empty()) { + const auto &CurNode = Stack.back(); + Stack.pop_back(); + FuncDeclNode = CurNode.get(); + if (FuncDeclNode != nullptr) { + break; + } + else { + for (const auto &Parent : Finder->getASTContext().getParents(CurNode)) + Stack.push_back(Parent); + } + } + if (FuncDeclNode == nullptr) { + return false; + } + else { + return InnerMatcher.matches(FuncDeclNode->getReturnType(), Finder, Builder); + } +} + /// Matches if the type location of a node matches the inner matcher. /// /// Examples: diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -314,6 +314,7 @@ REGISTER_MATCHER(hasEitherOperand); REGISTER_MATCHER(hasElementType); REGISTER_MATCHER(hasElse); + REGISTER_MATCHER(hasExpectedReturnType); REGISTER_MATCHER(hasExplicitSpecifier); REGISTER_MATCHER(hasExternalFormalLinkage); REGISTER_MATCHER(hasFalseExpression);