brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · 2f54b17 Raw
76 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 "TriviallyDestructibleCheck.h"10#include "../utils/LexerUtils.h"11#include "../utils/Matchers.h"12#include "clang/AST/ASTContext.h"13#include "clang/ASTMatchers/ASTMatchFinder.h"14 15using namespace clang::ast_matchers;16using namespace clang::ast_matchers::internal;17using namespace clang::tidy::matchers;18 19namespace clang::tidy::performance {20 21namespace {22 23AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); }24 25AST_MATCHER_P(CXXRecordDecl, hasBase, Matcher<QualType>, InnerMatcher) {26  for (const CXXBaseSpecifier &BaseSpec : Node.bases()) {27    const QualType BaseType = BaseSpec.getType();28    if (InnerMatcher.matches(BaseType, Finder, Builder))29      return true;30  }31  return false;32}33 34} // namespace35 36void TriviallyDestructibleCheck::registerMatchers(MatchFinder *Finder) {37  Finder->addMatcher(38      cxxDestructorDecl(39          isDefaulted(),40          unless(anyOf(isFirstDecl(), isVirtual(),41                       ofClass(cxxRecordDecl(42                           anyOf(hasBase(unless(isTriviallyDestructible())),43                                 has(fieldDecl(unless(44                                     hasType(isTriviallyDestructible()))))))))))45          .bind("decl"),46      this);47}48 49void TriviallyDestructibleCheck::check(const MatchFinder::MatchResult &Result) {50  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXDestructorDecl>("decl");51 52  // Get locations of both first and out-of-line declarations.53  const SourceManager &SM = *Result.SourceManager;54  const auto *FirstDecl = cast<CXXMethodDecl>(MatchedDecl->getFirstDecl());55  const SourceLocation FirstDeclEnd = utils::lexer::findNextTerminator(56      FirstDecl->getEndLoc(), SM, getLangOpts());57  const CharSourceRange SecondDeclRange = CharSourceRange::getTokenRange(58      MatchedDecl->getBeginLoc(),59      utils::lexer::findNextTerminator(MatchedDecl->getEndLoc(), SM,60                                       getLangOpts()));61  if (FirstDeclEnd.isInvalid() || SecondDeclRange.isInvalid())62    return;63 64  // Report diagnostic.65  diag(FirstDecl->getLocation(),66       "class %0 can be made trivially destructible by defaulting the "67       "destructor on its first declaration")68      << FirstDecl->getParent()69      << FixItHint::CreateInsertion(FirstDeclEnd, " = default")70      << FixItHint::CreateRemoval(SecondDeclRange);71  diag(MatchedDecl->getLocation(), "destructor definition is here",72       DiagnosticIDs::Note);73}74 75} // namespace clang::tidy::performance76