reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
//===--- MisplacedConstCheck.cpp - clang-tidy------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "MisplacedConstCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace misc {

void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      valueDecl(hasType(isConstQualified()),
                hasType(typedefType(hasDeclaration(
                    typedefDecl(hasType(pointerType(unless(pointee(
                                    anyOf(isConstQualified(),
                                          ignoringParens(functionType())))))))
                        .bind("typedef")))))
          .bind("decl"),
      this);
}

static QualType guessAlternateQualification(ASTContext &Context, QualType QT) {
  // We're given a QualType from a typedef where the qualifiers apply to the
  // pointer instead of the pointee. Strip the const qualifier from the pointer
  // type and add it to the pointee instead.
  if (!QT->isPointerType())
    return QT;

  Qualifiers Quals = QT.getLocalQualifiers();
  Quals.removeConst();

  QualType NewQT = Context.getPointerType(
      QualType(QT->getPointeeType().getTypePtr(), Qualifiers::Const));
  return NewQT.withCVRQualifiers(Quals.getCVRQualifiers());
}

void MisplacedConstCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Var = Result.Nodes.getNodeAs<ValueDecl>("decl");
  const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("typedef");
  ASTContext &Ctx = *Result.Context;
  QualType CanQT = Var->getType().getCanonicalType();

  diag(Var->getLocation(), "%0 declared with a const-qualified typedef type; "
                           "results in the type being '%1' instead of '%2'")
      << Var << CanQT.getAsString(Ctx.getPrintingPolicy())
      << guessAlternateQualification(Ctx, CanQT)
             .getAsString(Ctx.getPrintingPolicy());
  diag(Typedef->getLocation(), "typedef declared here", DiagnosticIDs::Note);
}

} // namespace misc
} // namespace tidy
} // namespace clang