brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · d3830a0 Raw
145 lines · cpp
1//==-- DebugContainerModeling.cpp ---------------------------------*- C++ -*--//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// Defines a checker for debugging iterator modeling.10//11//===----------------------------------------------------------------------===//12 13#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"14#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"15#include "clang/StaticAnalyzer/Core/Checker.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"19 20#include "Iterator.h"21 22using namespace clang;23using namespace ento;24using namespace iterator;25 26namespace {27 28class DebugContainerModeling29  : public Checker<eval::Call> {30 31  const BugType DebugMsgBugType{this, "Checking analyzer assumptions", "debug",32                                /*SuppressOnSink=*/true};33 34  template <typename Getter>35  void analyzerContainerDataField(const CallExpr *CE, CheckerContext &C,36                                  Getter get) const;37  void analyzerContainerBegin(const CallExpr *CE, CheckerContext &C) const;38  void analyzerContainerEnd(const CallExpr *CE, CheckerContext &C) const;39  ExplodedNode *reportDebugMsg(llvm::StringRef Msg, CheckerContext &C) const;40 41  typedef void (DebugContainerModeling::*FnCheck)(const CallExpr *,42                                                 CheckerContext &) const;43 44  CallDescriptionMap<FnCheck> Callbacks = {45      {{CDM::SimpleFunc, {"clang_analyzer_container_begin"}, 1},46       &DebugContainerModeling::analyzerContainerBegin},47      {{CDM::SimpleFunc, {"clang_analyzer_container_end"}, 1},48       &DebugContainerModeling::analyzerContainerEnd},49  };50 51public:52  bool evalCall(const CallEvent &Call, CheckerContext &C) const;53};54 55} // namespace56 57bool DebugContainerModeling::evalCall(const CallEvent &Call,58                                      CheckerContext &C) const {59  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());60  if (!CE)61    return false;62 63  const FnCheck *Handler = Callbacks.lookup(Call);64  if (!Handler)65    return false;66 67  (this->**Handler)(CE, C);68  return true;69}70 71template <typename Getter>72void DebugContainerModeling::analyzerContainerDataField(const CallExpr *CE,73                                                        CheckerContext &C,74                                                        Getter get) const {75  if (CE->getNumArgs() == 0) {76    reportDebugMsg("Missing container argument", C);77    return;78  }79 80  auto State = C.getState();81  const MemRegion *Cont = C.getSVal(CE->getArg(0)).getAsRegion();82  if (Cont) {83    const auto *Data = getContainerData(State, Cont);84    if (Data) {85      SymbolRef Field = get(Data);86      if (Field) {87        State = State->BindExpr(CE, C.getLocationContext(),88                                nonloc::SymbolVal(Field));89 90        // Progpagate interestingness from the container's data (marked91        // interesting by an `ExprInspection` debug call to the container92        // itself.93        const NoteTag *InterestingTag =94          C.getNoteTag(95              [Cont, Field](PathSensitiveBugReport &BR) -> std::string {96                if (BR.isInteresting(Field)) {97                  BR.markInteresting(Cont);98                }99                return "";100              });101        C.addTransition(State, InterestingTag);102        return;103      }104    }105  }106 107  auto &BVF = C.getSValBuilder().getBasicValueFactory();108  State = State->BindExpr(CE, C.getLocationContext(),109                   nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));110}111 112void DebugContainerModeling::analyzerContainerBegin(const CallExpr *CE,113                                                    CheckerContext &C) const {114  analyzerContainerDataField(CE, C, [](const ContainerData *D) {115      return D->getBegin();116    });117}118 119void DebugContainerModeling::analyzerContainerEnd(const CallExpr *CE,120                                                  CheckerContext &C) const {121  analyzerContainerDataField(CE, C, [](const ContainerData *D) {122      return D->getEnd();123    });124}125 126ExplodedNode *DebugContainerModeling::reportDebugMsg(llvm::StringRef Msg,127                                                     CheckerContext &C) const {128  ExplodedNode *N = C.generateNonFatalErrorNode();129  if (!N)130    return nullptr;131 132  auto &BR = C.getBugReporter();133  BR.emitReport(134      std::make_unique<PathSensitiveBugReport>(DebugMsgBugType, Msg, N));135  return N;136}137 138void ento::registerDebugContainerModeling(CheckerManager &mgr) {139  mgr.registerChecker<DebugContainerModeling>();140}141 142bool ento::shouldRegisterDebugContainerModeling(const CheckerManager &mgr) {143  return true;144}145