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;
35 ::clang::DynTypedNode Node;
38AST_MATCHER_P(MaterializeTemporaryExpr, isExtendedByDeclBoundTo, StringRef,
40 NotExtendedByDeclBoundToPredicate Predicate{
41 ID, ::clang::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(unless(isExpansionInSystemHeader()),
61 hasType(qualType(references(qualType().bind(
"type")))),
63 hasInitializer(expr(hasDescendant(
64 materializeTemporaryExpr(
65 isExtendedByDeclBoundTo(
"var"),
66 has(expr(anyOf(cxxTemporaryObjectExpr(), initListExpr(),
68 hasType(qualType(equalsBoundNode(
"type"))))))
69 .bind(
"temporary"))))),
74 const MatchFinder::MatchResult &Result) {
75 const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>(
"var");
76 const auto *MatchedTemporary = Result.Nodes.getNodeAs<Expr>(
"temporary");
78 diag(MatchedDecl->getLocation(),
79 "reference variable %0 extends the lifetime of a just-constructed "
80 "temporary object %1, consider changing reference to value")
81 << 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)