10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
21struct NotExtendedByDeclBoundToPredicate {
22 bool operator()(
const internal::BoundNodesMap &Nodes)
const {
23 const auto *Other = Nodes.getNodeAs<ValueDecl>(ID);
27 const auto *Self = Node.get<MaterializeTemporaryExpr>();
31 return Self->getExtendingDecl() != Other;
38AST_MATCHER_P(MaterializeTemporaryExpr, isExtendedByDeclBoundTo, StringRef,
40 const NotExtendedByDeclBoundToPredicate Predicate{ID,
41 DynTypedNode::create(Node)};
42 return Builder->removeBindings(Predicate);
48 const LangOptions &LangOpts)
const {
49 return LangOpts.CPlusPlus;
52std::optional<TraversalKind>
58 MatchFinder *Finder) {
60 varDecl(hasType(qualType(references(qualType().bind(
"type")))),
62 hasInitializer(expr(hasDescendant(
63 materializeTemporaryExpr(
64 isExtendedByDeclBoundTo(
"var"),
65 has(expr(anyOf(cxxTemporaryObjectExpr(), initListExpr(),
67 hasType(qualType(equalsBoundNode(
"type"))))))
68 .bind(
"temporary"))))),
73 const MatchFinder::MatchResult &Result) {
74 const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>(
"var");
75 const auto *MatchedTemporary = Result.Nodes.getNodeAs<Expr>(
"temporary");
77 diag(MatchedDecl->getLocation(),
78 "reference variable %0 extends the lifetime of a just-constructed "
79 "temporary object %1, consider changing reference to value")
80 << MatchedDecl << MatchedTemporary->getType();
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
std::optional< TraversalKind > getCheckTraversalKind() const override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)