brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · 398bee1 Raw
85 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ReferenceToConstructedTemporaryCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::readability {16 17namespace {18 19// Predicate structure to check if lifetime of temporary is not extended by20// ValueDecl pointed out by ID21struct NotExtendedByDeclBoundToPredicate {22  bool operator()(const internal::BoundNodesMap &Nodes) const {23    const auto *Other = Nodes.getNodeAs<ValueDecl>(ID);24    if (!Other)25      return true;26 27    const auto *Self = Node.get<MaterializeTemporaryExpr>();28    if (!Self)29      return true;30 31    return Self->getExtendingDecl() != Other;32  }33 34  StringRef ID;35  ::clang::DynTypedNode Node;36};37 38AST_MATCHER_P(MaterializeTemporaryExpr, isExtendedByDeclBoundTo, StringRef,39              ID) {40  const NotExtendedByDeclBoundToPredicate Predicate{41      ID, ::clang::DynTypedNode::create(Node)};42  return Builder->removeBindings(Predicate);43}44 45} // namespace46 47bool ReferenceToConstructedTemporaryCheck::isLanguageVersionSupported(48    const LangOptions &LangOpts) const {49  return LangOpts.CPlusPlus;50}51 52std::optional<TraversalKind>53ReferenceToConstructedTemporaryCheck::getCheckTraversalKind() const {54  return TK_AsIs;55}56 57void ReferenceToConstructedTemporaryCheck::registerMatchers(58    MatchFinder *Finder) {59  Finder->addMatcher(60      varDecl(unless(isExpansionInSystemHeader()),61              hasType(qualType(references(qualType().bind("type")))),62              decl().bind("var"),63              hasInitializer(expr(hasDescendant(64                  materializeTemporaryExpr(65                      isExtendedByDeclBoundTo("var"),66                      has(expr(anyOf(cxxTemporaryObjectExpr(), initListExpr(),67                                     cxxConstructExpr()),68                               hasType(qualType(equalsBoundNode("type"))))))69                      .bind("temporary"))))),70      this);71}72 73void ReferenceToConstructedTemporaryCheck::check(74    const MatchFinder::MatchResult &Result) {75  const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("var");76  const auto *MatchedTemporary = Result.Nodes.getNodeAs<Expr>("temporary");77 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();82}83 84} // namespace clang::tidy::readability85