llvm/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h

//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===//
//
// 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 file declares BugReporterVisitors, which are used to generate enhanced
//  diagnostic traces.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H

#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include <list>
#include <memory>
#include <optional>
#include <utility>

namespace clang {

class BinaryOperator;
class CFGBlock;
class DeclRefExpr;
class Expr;
class Stmt;

namespace ento {

class PathSensitiveBugReport;
class BugReporterContext;
class ExplodedNode;
class MemRegion;
class PathDiagnosticPiece;
PathDiagnosticPieceRef;

/// BugReporterVisitors are used to add custom diagnostics along a path.
class BugReporterVisitor : public llvm::FoldingSetNode {};

namespace bugreporter {

/// Specifies the type of tracking for an expression.
enum class TrackingKind {};

/// Defines a set of options altering tracking behavior.
struct TrackingOptions {};

/// Describes an event when the value got stored into a memory region.
///
/// As opposed to checker checkBind API, it reacts also to binds
/// generated by the checker as well.  It can be useful when the binding
/// happened as a result of evalCall, for example.
struct StoreInfo {};

class Tracker;
TrackerRef;

class ExpressionHandler;
class StoreHandler;

/// A generalized component for tracking expressions, values, and stores.
///
/// Tracker aimes at providing a sensible set of default behaviors that can be
/// used by any checker, while providing mechanisms to hook into any part of the
/// tracking process and insert checker-specific logic.
class Tracker : public llvm::RefCountedBase<Tracker> {};

/// Handles expressions during the tracking.
class ExpressionHandler {};

/// Handles stores during the tracking.
class StoreHandler {};

/// Visitor that tracks expressions and values.
class TrackingBugReporterVisitor : public BugReporterVisitor {};

/// Attempts to add visitors to track expression value back to its point of
/// origin.
///
/// \param N A node "downstream" from the evaluation of the statement.
/// \param E The expression value which we are tracking
/// \param R The bug report to which visitors should be attached.
/// \param Opts Tracking options specifying how we are tracking the value.
///
/// \return Whether or not the function was able to add visitors for this
///         statement. Note that returning \c true does not actually imply
///         that any visitors were added.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
                          PathSensitiveBugReport &R, TrackingOptions Opts = {};

/// Track how the value got stored into the given region and where it came
/// from.
///
/// \param V We're searching for the store where \c R received this value.
///        It may be either defined or undefined, but should not be unknown.
/// \param R The region we're tracking.
/// \param Opts Tracking options specifying how we want to track the value.
/// \param Origin Only adds notes when the last store happened in a
///        different stackframe to this one. Disregarded if the tracking kind
///        is thorough.
///        This is useful, because for non-tracked regions, notes about
///        changes to its value in a nested stackframe could be pruned, and
///        this visitor can prevent that without polluting the bugpath too
///        much.
void trackStoredValue(SVal V, const MemRegion *R,
                      PathSensitiveBugReport &Report, TrackingOptions Opts = {};

const Expr *getDerefExpr(const Stmt *S);

} // namespace bugreporter

class TrackConstraintBRVisitor final : public BugReporterVisitor {};

/// \class NilReceiverBRVisitor
/// Prints path notes when a message is sent to a nil receiver.
class NilReceiverBRVisitor final : public BugReporterVisitor {};

/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor final : public BugReporterVisitor {};

/// Suppress reports that might lead to known false positives.
///
/// Currently this suppresses reports based on locations of bugs.
class LikelyFalsePositiveSuppressionBRVisitor final
    : public BugReporterVisitor {};

/// When a region containing undefined value or '0' value is passed
/// as an argument in a call, marks the call as interesting.
///
/// As a result, BugReporter will not prune the path through the function even
/// if the region's contents are not modified/accessed by the call.
class UndefOrNullArgVisitor final : public BugReporterVisitor {};

class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {};

/// The visitor detects NoteTags and displays the event notes they contain.
class TagVisitor : public BugReporterVisitor {};

class ObjCMethodCall;
class CXXConstructorCall;

/// Put a diagnostic on return statement (or on } in its absence) of all inlined
/// functions for which some property remained unchanged.
/// Resulting diagnostics may read such as "Returning without writing to X".
///
/// Descendants can define what a "state change is", like a change of value
/// to a memory region, liveness, etc. For function calls where the state did
/// not change as defined, a custom note may be constructed.
///
/// For a minimal example, check out
/// clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp.
class NoStateChangeFuncVisitor : public BugReporterVisitor {};

/// Put a diagnostic on return statement of all inlined functions
/// for which  the region of interest \p RegionOfInterest was passed into,
/// but not written inside, and it has caused an undefined read or a null
/// pointer dereference outside.
class NoStoreFuncVisitor final : public NoStateChangeFuncVisitor {};

} // namespace ento
} // namespace clang

#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H