brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · c8c0cfd 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 "MisplacedConstCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::misc {16 17void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) {18  auto NonConstAndNonFunctionPointerType = hasType(pointerType(unless(19      pointee(anyOf(isConstQualified(), ignoringParens(functionType()))))));20 21  Finder->addMatcher(22      valueDecl(23          hasType(qualType(isConstQualified(),24                           typedefType(hasDeclaration(anyOf(25                               typedefDecl(NonConstAndNonFunctionPointerType)26                                   .bind("typedef"),27                               typeAliasDecl(NonConstAndNonFunctionPointerType)28                                   .bind("typeAlias")))))))29          .bind("decl"),30      this);31}32 33static QualType guessAlternateQualification(ASTContext &Context, QualType QT) {34  // We're given a QualType from a typedef where the qualifiers apply to the35  // pointer instead of the pointee. Strip the const qualifier from the pointer36  // type and add it to the pointee instead.37  if (!QT->isPointerType())38    return QT;39 40  Qualifiers Quals = QT.getLocalQualifiers();41  Quals.removeConst();42 43  const QualType NewQT = Context.getPointerType(44      QualType(QT->getPointeeType().getTypePtr(), Qualifiers::Const));45  return NewQT.withCVRQualifiers(Quals.getCVRQualifiers());46}47 48void MisplacedConstCheck::check(const MatchFinder::MatchResult &Result) {49  const auto *Var = Result.Nodes.getNodeAs<ValueDecl>("decl");50  ASTContext &Ctx = *Result.Context;51  const QualType CanQT = Var->getType().getCanonicalType();52 53  SourceLocation AliasLoc;54  const char *AliasType = nullptr;55  if (const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("typedef")) {56    AliasLoc = Typedef->getLocation();57    AliasType = "typedef";58  } else if (const auto *TypeAlias =59                 Result.Nodes.getNodeAs<TypeAliasDecl>("typeAlias")) {60    AliasLoc = TypeAlias->getLocation();61    AliasType = "type alias";62  } else {63    llvm_unreachable("registerMatchers has registered an unknown matcher,"64                     " code out of sync");65  }66 67  diag(Var->getLocation(), "%0 declared with a const-qualified %1; "68                           "results in the type being '%2' instead of '%3'")69      << Var << AliasType << CanQT.getAsString(Ctx.getPrintingPolicy())70      << guessAlternateQualification(Ctx, CanQT)71             .getAsString(Ctx.getPrintingPolicy());72  diag(AliasLoc, "%0 declared here", DiagnosticIDs::Note) << AliasType;73}74 75} // namespace clang::tidy::misc76