================ @@ -0,0 +1,283 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// This checker uses a 7-step algorithm to accomplish scope analysis of a +// variable and determine if it's in too large a scope. Note that the +// clang-tidy framework is aimed mainly at supporting text-manipulation, +// diagnostics, or common AST patterns. Scope reduction analysis is +// quite specialized, and there's not much support specifically for +// those steps. Perhaps someone else knows better and can help simplify +// this code in a more concrete way other than simply suggesting it can +// be simpler. +// +// The 7-step algorithm used by this checker for scope reduction analysis is: +// 1) Filter out variables declared in for-loop initializations +// - Those variables are already in optimal scope, and can be skipped +// 2) Collect variable uses +// - find all DeclRefExpr nodes that reference the variable +// 3) Build scope chains +// - for each use, find all compound statements that contain it (from +// innermost to outermost) +// 4) Find the innermost compound statement that contains all uses +// - This is the smallest scope where the variable could be declared +// 5) Find declaration scope +// - Locate the compound statement containing the variable declaration +// 6) Verify nesting +// - Ensure the usage scope is actually nested within the declaration scope +// 7) Alternate analysis - check for for-loop initialization opportunity +// - This is only run if compound stmt analysis didn't find smaller scope +// - Only check local variables, not parameters +// - Determine if all uses are within the same for-loop and suggest +// for-loop initialization +// +// The algo works by finding the smallest scope that could contain the variable +// declaration while still encompassing all it's uses. + +#include "ScopeReductionCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::misc { + +// TODO: Try using utils::decl_ref_expr::allDeclRefExprs here. +static void +collectVariableUses(const Stmt *S, const VarDecl *Var, + llvm::SmallVector<const DeclRefExpr *, 8> &Uses) { + if (!S) + return; + + if (const auto *DRE = dyn_cast<DeclRefExpr>(S)) { + if (DRE->getDecl() == Var) + Uses.push_back(DRE); + } + + for (const Stmt *Child : S->children()) + collectVariableUses(Child, Var, Uses); +} + +void ScopeReductionCheck::registerMatchers(MatchFinder *Finder) { + // TODO: Try adding unless(hasParent(declStmt(hasParent(forStmt( to matcher + // to simplify check code. + Finder->addMatcher(varDecl(hasLocalStorage()).bind("var"), this); +} + +void ScopeReductionCheck::check( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var"); + if (!Var) ---------------- zwuis wrote:
Use `assert`. `check` will be called only if the matcher matches anything. https://github.com/llvm/llvm-project/pull/175429 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
