brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · a4edd2b Raw
95 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 "RedundantTypenameCheck.h"10#include "clang/AST/TypeLoc.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/ASTMatchers/ASTMatchers.h"13#include "clang/Basic/Diagnostic.h"14#include "clang/Lex/Lexer.h"15 16using namespace clang::ast_matchers;17 18namespace clang::tidy::readability {19 20void RedundantTypenameCheck::registerMatchers(MatchFinder *Finder) {21  Finder->addMatcher(typeLoc(unless(hasAncestor(decl(isInstantiated()))))22                         .bind("nonDependentTypeLoc"),23                     this);24 25  if (!getLangOpts().CPlusPlus20)26    return;27 28  const auto InImplicitTypenameContext = anyOf(29      hasParent(decl(anyOf(30          typedefNameDecl(), templateTypeParmDecl(), nonTypeTemplateParmDecl(),31          friendDecl(), fieldDecl(),32          varDecl(hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl())),33                  unless(parmVarDecl())),34          parmVarDecl(hasParent(expr(requiresExpr()))),35          parmVarDecl(hasParent(typeLoc(hasParent(decl(36              anyOf(cxxMethodDecl(), hasParent(friendDecl()),37                    functionDecl(has(nestedNameSpecifier())),38                    cxxDeductionGuideDecl(hasDeclContext(recordDecl())))))))),39          // Match return types.40          functionDecl(unless(cxxConversionDecl()))))),41      hasParent(expr(anyOf(cxxNamedCastExpr(), cxxNewExpr()))));42  Finder->addMatcher(43      typeLoc(InImplicitTypenameContext).bind("dependentTypeLoc"), this);44}45 46void RedundantTypenameCheck::check(const MatchFinder::MatchResult &Result) {47  const SourceLocation ElaboratedKeywordLoc = [&] {48    if (const auto *NonDependentTypeLoc =49            Result.Nodes.getNodeAs<TypeLoc>("nonDependentTypeLoc")) {50      if (const auto TL = NonDependentTypeLoc->getAs<TypedefTypeLoc>())51        return TL.getElaboratedKeywordLoc();52 53      if (const auto TL = NonDependentTypeLoc->getAs<TagTypeLoc>())54        return TL.getElaboratedKeywordLoc();55 56      if (const auto TL = NonDependentTypeLoc57                              ->getAs<DeducedTemplateSpecializationTypeLoc>())58        return TL.getElaboratedKeywordLoc();59 60      if (const auto TL =61              NonDependentTypeLoc->getAs<TemplateSpecializationTypeLoc>())62        if (!TL.getType()->isDependentType())63          return TL.getElaboratedKeywordLoc();64    } else {65      TypeLoc InnermostTypeLoc =66          *Result.Nodes.getNodeAs<TypeLoc>("dependentTypeLoc");67      while (const TypeLoc Next = InnermostTypeLoc.getNextTypeLoc())68        InnermostTypeLoc = Next;69 70      if (const auto TL = InnermostTypeLoc.getAs<DependentNameTypeLoc>())71        return TL.getElaboratedKeywordLoc();72 73      if (const auto TL =74              InnermostTypeLoc.getAs<TemplateSpecializationTypeLoc>())75        return TL.getElaboratedKeywordLoc();76    }77 78    return SourceLocation();79  }();80 81  if (ElaboratedKeywordLoc.isInvalid())82    return;83 84  if (Token ElaboratedKeyword;85      Lexer::getRawToken(ElaboratedKeywordLoc, ElaboratedKeyword,86                         *Result.SourceManager, getLangOpts()) ||87      ElaboratedKeyword.getRawIdentifier() != "typename")88    return;89 90  diag(ElaboratedKeywordLoc, "redundant 'typename'")91      << FixItHint::CreateRemoval(ElaboratedKeywordLoc);92}93 94} // namespace clang::tidy::readability95