brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 1bbb9c8 Raw
109 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 "RedundantMemberInitCheck.h"10#include "../utils/LexerUtils.h"11#include "../utils/Matchers.h"12#include "clang/AST/ASTContext.h"13#include "clang/ASTMatchers/ASTMatchFinder.h"14#include "clang/Lex/Lexer.h"15 16using namespace clang::ast_matchers;17using namespace clang::tidy::matchers;18 19namespace clang::tidy::readability {20 21static SourceRange22getFullInitRangeInclWhitespaces(SourceRange Range, const SourceManager &SM,23                                const LangOptions &LangOpts) {24  const Token PrevToken =25      utils::lexer::getPreviousToken(Range.getBegin(), SM, LangOpts, false);26  if (PrevToken.is(tok::unknown))27    return Range;28 29  if (PrevToken.isNot(tok::equal))30    return {PrevToken.getEndLoc(), Range.getEnd()};31 32  return getFullInitRangeInclWhitespaces(33      {PrevToken.getLocation(), Range.getEnd()}, SM, LangOpts);34}35 36void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {37  Options.store(Opts, "IgnoreBaseInCopyConstructors",38                IgnoreBaseInCopyConstructors);39}40 41void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {42  auto ConstructorMatcher =43      cxxConstructExpr(44          argumentCountIs(0),45          hasDeclaration(cxxConstructorDecl(46              ofClass(cxxRecordDecl(unless(isTriviallyDefaultConstructible()))47                          .bind("class")))))48          .bind("construct");49 50  auto HasUnionAsParent = hasParent(recordDecl(isUnion()));51 52  auto HasTypeEqualToConstructorClass = hasType(qualType(53      hasCanonicalType(qualType(hasDeclaration(equalsBoundNode("class"))))));54 55  Finder->addMatcher(56      cxxConstructorDecl(57          unless(isDelegatingConstructor()), ofClass(unless(isUnion())),58          forEachConstructorInitializer(59              cxxCtorInitializer(60                  withInitializer(ConstructorMatcher),61                  anyOf(isBaseInitializer(),62                        forField(fieldDecl(unless(hasType(isConstQualified())),63                                           unless(HasUnionAsParent),64                                           HasTypeEqualToConstructorClass))))65                  .bind("init")))66          .bind("constructor"),67      this);68 69  Finder->addMatcher(fieldDecl(hasInClassInitializer(ConstructorMatcher),70                               HasTypeEqualToConstructorClass,71                               unless(HasUnionAsParent))72                         .bind("field"),73                     this);74}75 76void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {77  const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");78 79  if (const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field")) {80    const Expr *Init = Field->getInClassInitializer();81    diag(Construct->getExprLoc(), "initializer for member %0 is redundant")82        << Field83        << FixItHint::CreateRemoval(getFullInitRangeInclWhitespaces(84               Init->getSourceRange(), *Result.SourceManager, getLangOpts()));85    return;86  }87 88  const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init");89  const auto *ConstructorDecl =90      Result.Nodes.getNodeAs<CXXConstructorDecl>("constructor");91 92  if (IgnoreBaseInCopyConstructors && ConstructorDecl->isCopyConstructor() &&93      Init->isBaseInitializer())94    return;95 96  if (Init->isAnyMemberInitializer()) {97    diag(Init->getSourceLocation(), "initializer for member %0 is redundant")98        << Init->getAnyMember()99        << FixItHint::CreateRemoval(Init->getSourceRange());100  } else {101    diag(Init->getSourceLocation(),102         "initializer for base class %0 is redundant")103        << Construct->getType()104        << FixItHint::CreateRemoval(Init->getSourceRange());105  }106}107 108} // namespace clang::tidy::readability109