#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/Z3CrosscheckVisitor.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
usingnamespaceclang;
usingnamespaceento;
usingnamespacellvm;
#define DEBUG_TYPE …
STATISTIC(MaxBugClassSize,
"The maximum number of bug reports in the same equivalence class");
STATISTIC(MaxValidBugClassSize,
"The maximum number of bug reports in the same equivalence class "
"where at least one report is valid (not suppressed)");
STATISTIC(NumTimesReportPassesZ3, "Number of reports passed Z3");
STATISTIC(NumTimesReportRefuted, "Number of reports refuted by Z3");
STATISTIC(NumTimesReportEQClassAborted,
"Number of times a report equivalence class was aborted by the Z3 "
"oracle heuristic");
STATISTIC(NumTimesReportEQClassWasExhausted,
"Number of times all reports of an equivalence class was refuted");
BugReporterVisitor::~BugReporterVisitor() = default;
void BugReporterContext::anchor() { … }
namespace {
CallWithEntry;
CallWithEntryStack;
VisitorsDiagnosticsTy;
LocationContextMap;
class PathDiagnosticConstruct { … };
class PathDiagnosticBuilder : public BugReporterContext { … };
}
StackHintGenerator::~StackHintGenerator() = default;
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ … }
std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
unsigned ArgIndex) { … }
static PathDiagnosticEventPiece *
eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
PathDiagnosticEventPiece *Y) { … }
static void removeRedundantMsgs(PathPieces &path) { … }
static bool removeUnneededCalls(const PathDiagnosticConstruct &C,
PathPieces &pieces,
const PathSensitiveBugReport *R,
bool IsInteresting = false) { … }
static void removePopUpNotes(PathPieces &Path) { … }
static bool hasImplicitBody(const Decl *D) { … }
static void
adjustCallLocations(PathPieces &Pieces,
PathDiagnosticLocation *LastCallLocation = nullptr) { … }
static void removeEdgesToDefaultInitializers(PathPieces &Pieces) { … }
static void removePiecesWithInvalidLocations(PathPieces &Pieces) { … }
PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
const PathDiagnosticConstruct &C) const { … }
PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
llvm::raw_string_ostream &os, const PathDiagnosticConstruct &C) const { … }
static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) { … }
static PathDiagnosticLocation
getEnclosingStmtLocation(const Stmt *S, const LocationContext *LC,
bool allowNestedContexts = false) { … }
void PathDiagnosticBuilder::updateStackPiecesWithMessage(
PathDiagnosticPieceRef P, const CallWithEntryStack &CallStack) const { … }
static void CompactMacroExpandedPieces(PathPieces &path,
const SourceManager& SM);
PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForSwitchOP(
const PathDiagnosticConstruct &C, const CFGBlock *Dst,
PathDiagnosticLocation &Start) const { … }
PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForGotoOP(
const PathDiagnosticConstruct &C, const Stmt *S,
PathDiagnosticLocation &Start) const { … }
PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForBinaryOP(
const PathDiagnosticConstruct &C, const Stmt *T, const CFGBlock *Src,
const CFGBlock *Dst) const { … }
void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticConstruct &C, BlockEdge BE) const { … }
static bool isLoop(const Stmt *Term) { … }
static bool isJumpToFalseBranch(const BlockEdge *BE) { … }
static bool isContainedByStmt(const ParentMap &PM, const Stmt *S,
const Stmt *SubS) { … }
static const Stmt *getStmtBeforeCond(const ParentMap &PM, const Stmt *Term,
const ExplodedNode *N) { … }
static bool isInLoopBody(const ParentMap &PM, const Stmt *S, const Stmt *Term) { … }
static void addEdgeToPath(PathPieces &path,
PathDiagnosticLocation &PrevLoc,
PathDiagnosticLocation NewLoc) { … }
static const Stmt *getTerminatorCondition(const CFGBlock *B) { … }
constexpr llvm::StringLiteral StrEnteringLoop = …;
constexpr llvm::StringLiteral StrLoopBodyZero = …;
constexpr llvm::StringLiteral StrLoopRangeEmpty = …;
constexpr llvm::StringLiteral StrLoopCollectionEmpty = …;
static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(const SourceManager &SM, const ExplodedNode *N);
void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
PathDiagnosticConstruct &C, PathDiagnosticLocation &PrevLoc) const { … }
static std::unique_ptr<PathDiagnostic>
generateDiagnosticForBasicReport(const BasicBugReport *R,
const Decl *AnalysisEntryPoint) { … }
static std::unique_ptr<PathDiagnostic>
generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R,
const SourceManager &SM,
const Decl *AnalysisEntryPoint) { … }
static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { … }
static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) { … }
static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) { … }
OptimizedCallsSet;
static void addContextEdges(PathPieces &pieces, const LocationContext *LC) { … }
static void simplifySimpleBranches(PathPieces &pieces) { … }
static std::optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
SourceRange Range) { … }
static std::optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
const Stmt *S) { … }
static void removeContextCycles(PathPieces &Path, const SourceManager &SM) { … }
static bool lexicalContains(const ParentMap &PM, const Stmt *X, const Stmt *Y) { … }
static void removePunyEdges(PathPieces &path, const SourceManager &SM,
const ParentMap &PM) { … }
static void removeIdenticalEvents(PathPieces &path) { … }
static bool optimizeEdges(const PathDiagnosticConstruct &C, PathPieces &path,
OptimizedCallsSet &OCS) { … }
static void dropFunctionEntryEdge(const PathDiagnosticConstruct &C,
PathPieces &Path) { … }
static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) { … }
PathDiagnosticConstruct::PathDiagnosticConstruct(
const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode,
const PathSensitiveBugReport *R, const Decl *AnalysisEntryPoint)
: … { … }
PathDiagnosticBuilder::PathDiagnosticBuilder(
BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
PathSensitiveBugReport *r, const ExplodedNode *ErrorNode,
std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics)
: … { … }
std::unique_ptr<PathDiagnostic>
PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { … }
void BugType::anchor() { … }
LLVM_ATTRIBUTE_USED static bool
isDependency(const CheckerRegistryData &Registry, StringRef CheckerName) { … }
LLVM_ATTRIBUTE_USED static bool isHidden(const CheckerRegistryData &Registry,
StringRef CheckerName) { … }
PathSensitiveBugReport::PathSensitiveBugReport(
const BugType &bt, StringRef shortDesc, StringRef desc,
const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique)
: … { … }
void PathSensitiveBugReport::addVisitor(
std::unique_ptr<BugReporterVisitor> visitor) { … }
void PathSensitiveBugReport::clearVisitors() { … }
const Decl *PathSensitiveBugReport::getDeclWithIssue() const { … }
void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const { … }
void PathSensitiveBugReport::Profile(llvm::FoldingSetNodeID &hash) const { … }
template <class T>
static void insertToInterestingnessMap(
llvm::DenseMap<T, bugreporter::TrackingKind> &InterestingnessMap, T Val,
bugreporter::TrackingKind TKind) { … }
void PathSensitiveBugReport::markInteresting(SymbolRef sym,
bugreporter::TrackingKind TKind) { … }
void PathSensitiveBugReport::markNotInteresting(SymbolRef sym) { … }
void PathSensitiveBugReport::markInteresting(const MemRegion *R,
bugreporter::TrackingKind TKind) { … }
void PathSensitiveBugReport::markNotInteresting(const MemRegion *R) { … }
void PathSensitiveBugReport::markInteresting(SVal V,
bugreporter::TrackingKind TKind) { … }
void PathSensitiveBugReport::markInteresting(const LocationContext *LC) { … }
std::optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(SVal V) const { … }
std::optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(SymbolRef sym) const { … }
std::optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(const MemRegion *R) const { … }
bool PathSensitiveBugReport::isInteresting(SVal V) const { … }
bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const { … }
bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const { … }
bool PathSensitiveBugReport::isInteresting(const LocationContext *LC) const { … }
const Stmt *PathSensitiveBugReport::getStmt() const { … }
ArrayRef<SourceRange>
PathSensitiveBugReport::getRanges() const { … }
PathDiagnosticLocation
PathSensitiveBugReport::getLocation() const { … }
const ExplodedGraph &PathSensitiveBugReporter::getGraph() const { … }
ProgramStateManager &PathSensitiveBugReporter::getStateManager() const { … }
BugReporter::BugReporter(BugReporterData &D)
: … { … }
BugReporter::~BugReporter() { … }
void BugReporter::FlushReports() { … }
namespace {
class BugPathInfo { … };
class BugPathGetter { … };
}
BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
ArrayRef<PathSensitiveBugReport *> &bugReports) { … }
BugPathInfo *BugPathGetter::getNextBugPath() { … }
static void CompactMacroExpandedPieces(PathPieces &path,
const SourceManager& SM) { … }
static std::unique_ptr<VisitorsDiagnosticsTy>
generateVisitorsDiagnostics(PathSensitiveBugReport *R,
const ExplodedNode *ErrorNode,
BugReporterContext &BRC) { … }
std::optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport(
ArrayRef<PathSensitiveBugReport *> &bugReports,
PathSensitiveBugReporter &Reporter) { … }
std::unique_ptr<DiagnosticForConsumerMapTy>
PathSensitiveBugReporter::generatePathDiagnostics(
ArrayRef<PathDiagnosticConsumer *> consumers,
ArrayRef<PathSensitiveBugReport *> &bugReports) { … }
void BugReporter::emitReport(std::unique_ptr<BugReport> R) { … }
void PathSensitiveBugReporter::emitReport(std::unique_ptr<BugReport> R) { … }
namespace {
struct FRIEC_WLItem { … };
}
BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass(
BugReportEquivClass &EQ, SmallVectorImpl<BugReport *> &bugReports) { … }
void BugReporter::FlushReport(BugReportEquivClass& EQ) { … }
static void populateExecutedLinesWithFunctionSignature(
const Decl *Signature, const SourceManager &SM,
FilesToLineNumsMap &ExecutedLines) { … }
static void populateExecutedLinesWithStmt(
const Stmt *S, const SourceManager &SM,
FilesToLineNumsMap &ExecutedLines) { … }
static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(const SourceManager &SM, const ExplodedNode *N) { … }
std::unique_ptr<DiagnosticForConsumerMapTy>
BugReporter::generateDiagnosticForConsumerMap(
BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
ArrayRef<BugReport *> bugReports) { … }
static PathDiagnosticCallPiece *
getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
const SourceManager &SMgr) { … }
static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) { … }
std::unique_ptr<DiagnosticForConsumerMapTy>
PathSensitiveBugReporter::generateDiagnosticForConsumerMap(
BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
ArrayRef<BugReport *> bugReports) { … }
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
const CheckerBase *Checker, StringRef Name,
StringRef Category, StringRef Str,
PathDiagnosticLocation Loc,
ArrayRef<SourceRange> Ranges,
ArrayRef<FixItHint> Fixits) { … }
void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
CheckerNameRef CheckName,
StringRef name, StringRef category,
StringRef str, PathDiagnosticLocation Loc,
ArrayRef<SourceRange> Ranges,
ArrayRef<FixItHint> Fixits) { … }
BugType *BugReporter::getBugTypeForName(CheckerNameRef CheckName,
StringRef name, StringRef category) { … }