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