10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
17 namespace llvm_check {
19 void PreferRegisterOverUnsignedCheck::registerMatchers(MatchFinder *Finder) {
20 auto RegisterClassMatch = hasType(
21 cxxRecordDecl(hasName(
"::llvm::Register")).bind(
"registerClassDecl"));
24 traverse(ast_type_traits::TK_AsIs,
26 hasType(qualType(isUnsignedInteger()).bind(
"varType")),
27 varDecl(hasInitializer(exprWithCleanups(
28 has(implicitCastExpr(has(cxxMemberCallExpr(
29 allOf(on(RegisterClassMatch),
30 has(memberExpr(hasDeclaration(
31 cxxConversionDecl())))))))))))
36 void PreferRegisterOverUnsignedCheck::check(
37 const MatchFinder::MatchResult &Result) {
38 const auto *VarType = Result.Nodes.getNodeAs<QualType>(
"varType");
39 const auto *UserVarDecl = Result.Nodes.getNodeAs<VarDecl>(
"var");
41 StringRef Replacement =
"llvm::Register";
42 const DeclContext *Context = UserVarDecl->getDeclContext();
44 if (
const auto *Namespace = dyn_cast<NamespaceDecl>(Context))
45 if (isa<TranslationUnitDecl>(Namespace->getDeclContext()) &&
46 Namespace->getName() ==
"llvm")
47 Replacement =
"Register";
48 for (
const auto *UsingDirective : Context->using_directives()) {
49 const NamespaceDecl *Namespace = UsingDirective->getNominatedNamespace();
50 if (isa<TranslationUnitDecl>(Namespace->getDeclContext()) &&
51 Namespace->getName() ==
"llvm")
52 Replacement =
"Register";
54 Context = Context->getParent();
56 diag(UserVarDecl->getLocation(),
57 "variable %0 declared as %1; use '%2' instead")
58 << UserVarDecl << *VarType << Replacement
59 << FixItHint::CreateReplacement(
60 UserVarDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(),