brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · fdb903a Raw
77 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "NondeterministicPointerIterationOrderCheck.h"10#include "clang/Lex/Lexer.h"11 12using namespace clang::ast_matchers;13 14namespace clang::tidy::bugprone {15 16void NondeterministicPointerIterationOrderCheck::registerMatchers(17    MatchFinder *Finder) {18  auto LoopVariable = varDecl(hasType(19      qualType(hasCanonicalType(anyOf(referenceType(), pointerType())))));20 21  auto RangeInit = declRefExpr(to(varDecl(22      hasType(recordDecl(hasAnyName("std::unordered_set", "std::unordered_map",23                                    "std::unordered_multiset",24                                    "std::unordered_multimap"))25                  .bind("recorddecl")))));26 27  Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVariable),28                                     hasRangeInit(RangeInit.bind("rangeinit")))29                         .bind("cxxForRangeStmt"),30                     this);31 32  auto SortFuncM = callee(functionDecl(hasAnyName(33      "std::is_sorted", "std::nth_element", "std::sort", "std::partial_sort",34      "std::partition", "std::stable_partition", "std::stable_sort")));35 36  auto IteratesPointerEltsM = hasArgument(37      0,38      cxxMemberCallExpr(on(hasType(cxxRecordDecl(has(fieldDecl(hasType(qualType(39          hasCanonicalType(pointsTo(hasCanonicalType(pointerType()))))))))))));40 41  Finder->addMatcher(42      callExpr(allOf(SortFuncM, IteratesPointerEltsM)).bind("sortsemantic"),43      this);44}45 46void NondeterministicPointerIterationOrderCheck::check(47    const MatchFinder::MatchResult &Result) {48  const auto *ForRangePointers =49      Result.Nodes.getNodeAs<CXXForRangeStmt>("cxxForRangeStmt");50 51  if ((ForRangePointers) && !(ForRangePointers->getBeginLoc().isMacroID())) {52    const auto *RangeInit = Result.Nodes.getNodeAs<Stmt>("rangeinit");53    if (const auto *ClassTemplate =54            Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(55                "recorddecl")) {56      const TemplateArgumentList &TemplateArgs =57          ClassTemplate->getTemplateArgs();58      const bool IsAlgoArgPointer =59          TemplateArgs[0].getAsType()->isPointerType();60 61      if (IsAlgoArgPointer) {62        const SourceRange R = RangeInit->getSourceRange();63        diag(R.getBegin(), "iteration of pointers is nondeterministic") << R;64      }65    }66    return;67  }68  const auto *SortPointers = Result.Nodes.getNodeAs<Stmt>("sortsemantic");69 70  if ((SortPointers) && !(SortPointers->getBeginLoc().isMacroID())) {71    const SourceRange R = SortPointers->getSourceRange();72    diag(R.getBegin(), "sorting pointers is nondeterministic") << R;73  }74}75 76} // namespace clang::tidy::bugprone77