[clang] [clang-tools-extra] RFC: [clang-tidy] [analyzer] Move nondeterministic pointer usage check to tidy (PR #110471)
Julian Schmidt via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 27 06:06:33 PDT 2024
================
@@ -0,0 +1,85 @@
+//===----- NondeterministicPointerIterationOrderCheck.cpp - clang-tidy ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "NondeterministicPointerIterationOrderCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void NondeterministicPointerIterationOrderCheck::registerMatchers(
+ MatchFinder *Finder) {
+
+ auto LoopVariable = varDecl(hasType(
+ qualType(hasCanonicalType(anyOf(referenceType(), pointerType())))));
+
+ auto RangeInit = declRefExpr(to(varDecl(
+ hasType(recordDecl(hasAnyName("std::unordered_set", "std::unordered_map",
+ "std::unordered_multiset",
+ "std::unordered_multimap"))
+ .bind("recorddecl")))));
+
+ Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVariable),
+ hasRangeInit(RangeInit.bind("rangeinit")))
+ .bind("cxxForRangeStmt"),
+ this);
+
+ auto SortFuncM = callee(functionDecl(hasAnyName(
+ "std::is_sorted", "std::nth_element", "std::sort", "std::partial_sort",
+ "std::partition", "std::stable_partition", "std::stable_sort")));
+
+ auto IteratesPointerEltsM = hasArgument(
+ 0,
+ cxxMemberCallExpr(on(hasType(cxxRecordDecl(has(fieldDecl(hasType(qualType(
+ hasCanonicalType(pointsTo(hasCanonicalType(pointerType()))))))))))));
+
+ Finder->addMatcher(
+ callExpr(allOf(SortFuncM, IteratesPointerEltsM)).bind("sortsemantic"),
+ this);
+}
+
+void NondeterministicPointerIterationOrderCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *ForRangePointers =
+ Result.Nodes.getNodeAs<CXXForRangeStmt>("cxxForRangeStmt");
+
+ if ((ForRangePointers) && !(ForRangePointers->getBeginLoc().isMacroID())) {
+ const auto *RangeInit = Result.Nodes.getNodeAs<Stmt>("rangeinit");
+ if (const auto *ClassTemplate =
+ Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
+ "recorddecl")) {
+ const TemplateArgumentList &TemplateArgs =
+ ClassTemplate->getTemplateArgs();
+ const llvm::StringRef AlgoName = ClassTemplate->getName();
+ const bool Unordered = AlgoName.contains("unordered");
+ const bool SetLike = AlgoName.contains("set");
+ const bool MapLike = AlgoName.contains("map");
----------------
5chmidti wrote:
I'm getting unused variable warnings for these in release mode because they are only ever used in the asserts. IMO these are not needed because we have constrained the node bound to `recorddecl` to the ones we are interested in.
https://github.com/llvm/llvm-project/pull/110471
More information about the cfe-commits
mailing list