Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp
35266 views
//===-- DebugIteratorModeling.cpp ---------------------------------*- C++ -*--//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines a checker for debugging iterator modeling.9//10//===----------------------------------------------------------------------===//1112#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"13#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"14#include "clang/StaticAnalyzer/Core/Checker.h"15#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"1819#include "Iterator.h"2021using namespace clang;22using namespace ento;23using namespace iterator;2425namespace {2627class DebugIteratorModeling28: public Checker<eval::Call> {2930const BugType DebugMsgBugType{this, "Checking analyzer assumptions", "debug",31/*SuppressOnSink=*/true};3233template <typename Getter>34void analyzerIteratorDataField(const CallExpr *CE, CheckerContext &C,35Getter get, SVal Default) const;36void analyzerIteratorPosition(const CallExpr *CE, CheckerContext &C) const;37void analyzerIteratorContainer(const CallExpr *CE, CheckerContext &C) const;38void analyzerIteratorValidity(const CallExpr *CE, CheckerContext &C) const;39ExplodedNode *reportDebugMsg(llvm::StringRef Msg, CheckerContext &C) const;4041typedef void (DebugIteratorModeling::*FnCheck)(const CallExpr *,42CheckerContext &) const;4344CallDescriptionMap<FnCheck> Callbacks = {45{{CDM::SimpleFunc, {"clang_analyzer_iterator_position"}, 1},46&DebugIteratorModeling::analyzerIteratorPosition},47{{CDM::SimpleFunc, {"clang_analyzer_iterator_container"}, 1},48&DebugIteratorModeling::analyzerIteratorContainer},49{{CDM::SimpleFunc, {"clang_analyzer_iterator_validity"}, 1},50&DebugIteratorModeling::analyzerIteratorValidity},51};5253public:54bool evalCall(const CallEvent &Call, CheckerContext &C) const;55};5657} // namespace5859bool DebugIteratorModeling::evalCall(const CallEvent &Call,60CheckerContext &C) const {61const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());62if (!CE)63return false;6465const FnCheck *Handler = Callbacks.lookup(Call);66if (!Handler)67return false;6869(this->**Handler)(CE, C);70return true;71}7273template <typename Getter>74void DebugIteratorModeling::analyzerIteratorDataField(const CallExpr *CE,75CheckerContext &C,76Getter get,77SVal Default) const {78if (CE->getNumArgs() == 0) {79reportDebugMsg("Missing iterator argument", C);80return;81}8283auto State = C.getState();84SVal V = C.getSVal(CE->getArg(0));85const auto *Pos = getIteratorPosition(State, V);86if (Pos) {87State = State->BindExpr(CE, C.getLocationContext(), get(Pos));88} else {89State = State->BindExpr(CE, C.getLocationContext(), Default);90}91C.addTransition(State);92}9394void DebugIteratorModeling::analyzerIteratorPosition(const CallExpr *CE,95CheckerContext &C) const {96auto &BVF = C.getSValBuilder().getBasicValueFactory();97analyzerIteratorDataField(CE, C, [](const IteratorPosition *P) {98return nonloc::SymbolVal(P->getOffset());99}, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));100}101102void DebugIteratorModeling::analyzerIteratorContainer(const CallExpr *CE,103CheckerContext &C) const {104auto &BVF = C.getSValBuilder().getBasicValueFactory();105analyzerIteratorDataField(CE, C, [](const IteratorPosition *P) {106return loc::MemRegionVal(P->getContainer());107}, loc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));108}109110void DebugIteratorModeling::analyzerIteratorValidity(const CallExpr *CE,111CheckerContext &C) const {112auto &BVF = C.getSValBuilder().getBasicValueFactory();113analyzerIteratorDataField(CE, C, [&BVF](const IteratorPosition *P) {114return115nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get((P->isValid()))));116}, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));117}118119ExplodedNode *DebugIteratorModeling::reportDebugMsg(llvm::StringRef Msg,120CheckerContext &C) const {121ExplodedNode *N = C.generateNonFatalErrorNode();122if (!N)123return nullptr;124125auto &BR = C.getBugReporter();126BR.emitReport(127std::make_unique<PathSensitiveBugReport>(DebugMsgBugType, Msg, N));128return N;129}130131void ento::registerDebugIteratorModeling(CheckerManager &mgr) {132mgr.registerChecker<DebugIteratorModeling>();133}134135bool ento::shouldRegisterDebugIteratorModeling(const CheckerManager &mgr) {136return true;137}138139140