1 //===--- AvoidNonConstGlobalVariablesCheck.cpp - clang-tidy ---------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AvoidNonConstGlobalVariablesCheck.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 14 using namespace clang::ast_matchers; 15 16 namespace clang { 17 namespace tidy { 18 namespace cppcoreguidelines { 19 20 namespace { 21 AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); } 22 } // namespace 23 24 void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) { 25 auto GlobalVariable = varDecl( 26 hasGlobalStorage(), 27 unless(anyOf( 28 isLocalVarDecl(), isConstexpr(), hasType(isConstQualified()), 29 hasType(referenceType())))); // References can't be changed, only the 30 // data they reference can be changed. 31 32 auto GlobalReferenceToNonConst = 33 varDecl(hasGlobalStorage(), hasType(referenceType()), 34 unless(hasType(references(qualType(isConstQualified()))))); 35 36 auto GlobalPointerToNonConst = 37 varDecl(hasGlobalStorage(), 38 hasType(pointerType(pointee(unless(isConstQualified()))))); 39 40 Finder->addMatcher(GlobalVariable.bind("non-const_variable"), this); 41 Finder->addMatcher(GlobalReferenceToNonConst.bind("indirection_to_non-const"), 42 this); 43 Finder->addMatcher(GlobalPointerToNonConst.bind("indirection_to_non-const"), 44 this); 45 } 46 47 void AvoidNonConstGlobalVariablesCheck::check( 48 const MatchFinder::MatchResult &Result) { 49 50 if (const auto *Variable = 51 Result.Nodes.getNodeAs<VarDecl>("non-const_variable")) { 52 diag(Variable->getLocation(), "variable %0 is non-const and globally " 53 "accessible, consider making it const") 54 << Variable; // FIXME: Add fix-it hint to Variable 55 // Don't return early, a non-const variable may also be a pointer or 56 // reference to non-const data. 57 } 58 59 if (const auto *VD = 60 Result.Nodes.getNodeAs<VarDecl>("indirection_to_non-const")) { 61 diag(VD->getLocation(), 62 "variable %0 provides global access to a non-const object; consider " 63 "making the %select{referenced|pointed-to}1 data 'const'") 64 << VD 65 << VD->getType()->isPointerType(); // FIXME: Add fix-it hint to Variable 66 } 67 } 68 69 } // namespace cppcoreguidelines 70 } // namespace tidy 71 } // namespace clang 72