1 //===--- MisplacedConstCheck.cpp - clang-tidy------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MisplacedConstCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 14 using namespace clang::ast_matchers; 15 16 namespace clang { 17 namespace tidy { 18 namespace misc { 19 20 void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) { 21 Finder->addMatcher( 22 valueDecl(hasType(isConstQualified()), 23 hasType(typedefType(hasDeclaration( 24 typedefDecl(hasType(pointerType(unless(pointee( 25 anyOf(isConstQualified(), 26 ignoringParens(functionType()))))))) 27 .bind("typedef"))))) 28 .bind("decl"), 29 this); 30 } 31 32 static QualType guessAlternateQualification(ASTContext &Context, QualType QT) { 33 // We're given a QualType from a typedef where the qualifiers apply to the 34 // pointer instead of the pointee. Strip the const qualifier from the pointer 35 // type and add it to the pointee instead. 36 if (!QT->isPointerType()) 37 return QT; 38 39 Qualifiers Quals = QT.getLocalQualifiers(); 40 Quals.removeConst(); 41 42 QualType NewQT = Context.getPointerType( 43 QualType(QT->getPointeeType().getTypePtr(), Qualifiers::Const)); 44 return NewQT.withCVRQualifiers(Quals.getCVRQualifiers()); 45 } 46 47 void MisplacedConstCheck::check(const MatchFinder::MatchResult &Result) { 48 const auto *Var = Result.Nodes.getNodeAs<ValueDecl>("decl"); 49 const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("typedef"); 50 ASTContext &Ctx = *Result.Context; 51 QualType CanQT = Var->getType().getCanonicalType(); 52 53 diag(Var->getLocation(), "%0 declared with a const-qualified typedef type; " 54 "results in the type being '%1' instead of '%2'") 55 << Var << CanQT.getAsString(Ctx.getPrintingPolicy()) 56 << guessAlternateQualification(Ctx, CanQT) 57 .getAsString(Ctx.getPrintingPolicy()); 58 diag(Typedef->getLocation(), "typedef declared here", DiagnosticIDs::Note); 59 } 60 61 } // namespace misc 62 } // namespace tidy 63 } // namespace clang 64