Skip to content

[analyzer] Add -ftime-trace scopes for region-store bindings and removeDead #125884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
Expand Down Expand Up @@ -1031,6 +1032,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
const LocationContext *LC,
const Stmt *DiagnosticStmt,
ProgramPoint::Kind K) {
llvm::TimeTraceScope TimeScope("ExprEngine::removeDead");
assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
&& "PostStmt is not generally supported by the SymbolReaper yet");
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/StaticAnalyzer/Core/RegionStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
#include <utility>
Expand Down Expand Up @@ -112,6 +113,13 @@ class BindingKey {

LLVM_DUMP_METHOD void dump() const;
};

std::string locDescr(Loc L) {
std::string S;
llvm::raw_string_ostream OS(S);
L.dumpToStream(OS);
return OS.str();
}
} // end anonymous namespace

BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
Expand Down Expand Up @@ -2408,6 +2416,8 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {

RegionBindingsRef
RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bind",
[&L]() { return locDescr(L); });
// We only care about region locations.
auto MemRegVal = L.getAs<loc::MemRegionVal>();
if (!MemRegVal)
Expand Down Expand Up @@ -2514,6 +2524,8 @@ RegionBindingsRef
RegionStoreManager::bindArray(RegionBindingsConstRef B,
const TypedValueRegion* R,
SVal Init) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindArray",
[R]() { return R->getDescriptiveName(); });

const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
QualType ElementTy = AT->getElementType();
Expand Down Expand Up @@ -2578,6 +2590,8 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
const TypedValueRegion* R,
SVal V) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindVector",
[R]() { return R->getDescriptiveName(); });
QualType T = R->getValueType();
const VectorType *VT = T->castAs<VectorType>(); // Use castAs for typedefs.

Expand Down Expand Up @@ -2700,6 +2714,8 @@ std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
const TypedValueRegion *R,
SVal V) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindStruct",
[R]() { return R->getDescriptiveName(); });
QualType T = R->getValueType();
assert(T->isStructureOrClassType());

Expand Down Expand Up @@ -2818,6 +2834,8 @@ RegionBindingsRef
RegionStoreManager::bindAggregate(RegionBindingsConstRef B,
const TypedRegion *R,
SVal Val) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindAggregate",
[R]() { return R->getDescriptiveName(); });
// Remove the old bindings, using 'R' as the root of all regions
// we will invalidate. Then add the new binding.
return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
Expand Down
24 changes: 24 additions & 0 deletions clang/test/Analysis/ftime-trace-bind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -ftime-trace=%t.raw.json -ftime-trace-granularity=0 -verify
// RUN: %python -c 'import json, sys; print(json.dumps(json.load(sys.stdin), indent=4))' < %t.raw.json > %t.formatted.json
// RUN: FileCheck --input-file=%t.formatted.json --check-prefix=CHECK %s

// CHECK: "name": "RegionStoreManager::bindArray",
// CHECK-NEXT: "args": {
//
// The below does not necessarily follow immediately,
// depending on what parts of the array are initialized first.
//
// CHECK: "detail": "'arr[0][1]'"
// CHECK-NEXT: }
//
// CHECK: "detail": "'arr[0]'"
// CHECK-NEXT: }
//
// CHECK: "detail": "'arr'"
// CHECK-NEXT: }

int f() {
int arr[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
return arr[1][0][1];
}
// expected-no-diagnostics
17 changes: 17 additions & 0 deletions clang/test/Analysis/ftime-trace-removeDead.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -ftime-trace=%t.raw.json -ftime-trace-granularity=0 -verify
// RUN: %python -c 'import json, sys; print(json.dumps(json.load(sys.stdin), indent=4))' < %t.raw.json > %t.formatted.json
// RUN: FileCheck --input-file=%t.formatted.json --check-prefix=CHECK %s

// The trace file is rather large, but it should contain at least one scope for removeDead:
//
// CHECK: "name": "ExprEngine::removeDead"

bool coin();
int f() {
int x = 0;
int y = 0;
while (coin()) {
x = 1;
}
return x / y; // expected-warning{{Division by zero}}
}