Skip to content

Commit f83589b

Browse files
committed
Add a test case demonstrating the use of explicitly set unsigned stats
1 parent ab54bbd commit f83589b

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,10 @@ def TaintTesterChecker : Checker<"TaintTest">,
15021502
HelpText<"Mark tainted symbols as such.">,
15031503
Documentation<NotDocumented>;
15041504

1505+
def UnsignedStatTesterChecker : Checker<"UnsignedStatTester">,
1506+
HelpText<"Test checker for demonstrating UnsignedEPStat usage.">,
1507+
Documentation<NotDocumented>;
1508+
15051509
// This checker *technically* depends on SteamChecker, but we don't allow
15061510
// dependency checkers to emit diagnostics, and a debug checker isn't worth
15071511
// the chore needed to create a modeling portion on its own. Since this checker

clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ add_clang_library(clangStaticAnalyzerCheckers
125125
UninitializedObject/UninitializedPointee.cpp
126126
UnixAPIChecker.cpp
127127
UnreachableCodeChecker.cpp
128+
UnsignedStatTesterChecker.cpp
128129
VforkChecker.cpp
129130
VLASizeChecker.cpp
130131
VAListChecker.cpp
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//== UnsignedStatTesterChecker.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-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This checker demonstrates the use of UnsignedEPStat for per-entry-point
10+
// statistics. It conditionally sets a statistic based on the entry point name.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15+
#include "clang/StaticAnalyzer/Core/Checker.h"
16+
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
17+
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18+
#include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h"
19+
20+
using namespace clang;
21+
using namespace ento;
22+
23+
#define DEBUG_TYPE "UnsignedStatTester"
24+
25+
static UnsignedEPStat DemoStat("DemoStat");
26+
27+
namespace {
28+
class UnsignedStatTesterChecker : public Checker<check::BeginFunction> {
29+
public:
30+
void checkBeginFunction(CheckerContext &C) const;
31+
};
32+
} // namespace
33+
34+
void UnsignedStatTesterChecker::checkBeginFunction(CheckerContext &C) const {
35+
const Decl *D = C.getLocationContext()->getDecl();
36+
if (!D)
37+
return;
38+
39+
std::string Name =
40+
D->getAsFunction() ? D->getAsFunction()->getNameAsString() : "";
41+
42+
// Conditionally set the statistic based on the function name
43+
if (Name == "func_one") {
44+
DemoStat.set(1);
45+
} else if (Name == "func_two") {
46+
DemoStat.set(2);
47+
} else if (Name == "func_three") {
48+
DemoStat.set(3);
49+
}
50+
// For any other function (e.g., "func_none"), don't set the statistic
51+
}
52+
53+
void ento::registerUnsignedStatTesterChecker(CheckerManager &mgr) {
54+
mgr.registerChecker<UnsignedStatTesterChecker>();
55+
}
56+
57+
bool ento::shouldRegisterUnsignedStatTesterChecker(const CheckerManager &mgr) {
58+
return true;
59+
}

clang/test/Analysis/analyzer-stats/entry-point-stats.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// REQUIRES: asserts
2-
// RUN: %clang_analyze_cc1 -analyzer-checker=core \
2+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.UnsignedStatTester \
33
// RUN: -analyzer-config dump-entry-point-stats-to-csv="%t.csv" \
44
// RUN: -verify %s
55
// RUN: %csv2json "%t.csv" | FileCheck --check-prefix=CHECK %s
@@ -8,6 +8,7 @@
88
// CHECK-NEXT: "c:@F@fib#i#": {
99
// CHECK-NEXT: "File": "{{.*}}/entry-point-stats.cpp",
1010
// CHECK-NEXT: "DebugName": "fib(unsigned int)",
11+
// CHECK-NEXT: "DemoStat": "",
1112
// CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}",
1213
// CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}",
1314
// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}",
@@ -42,9 +43,22 @@
4243
// CHECK-NEXT: "NumZ3QueriesDone": "{{[0-9]+}}",
4344
// CHECK-NEXT: "TimeSpentSolvingZ3Queries": "{{[0-9]+}}"
4445
// CHECK-NEXT: },
46+
// CHECK-NEXT: "c:@F@func_one#": {
47+
// CHECK-NEXT: "File": "{{.*}}/entry-point-stats.cpp",
48+
// CHECK-NEXT: "DebugName": "func_one()",
49+
// CHECK: "DemoStat": "1",
50+
// .... not interesting statistics
51+
// CHECK: },
52+
// CHECK-NEXT: "c:@F@func_two#": {
53+
// CHECK-NEXT: "File": "{{.*}}/entry-point-stats.cpp",
54+
// CHECK-NEXT: "DebugName": "func_two()",
55+
// CHECK: "DemoStat": "2",
56+
// .... not interesting statistics
57+
// CHECK: },
4558
// CHECK-NEXT: "c:@F@main#I#**C#": {
4659
// CHECK-NEXT: "File": "{{.*}}/entry-point-stats.cpp",
4760
// CHECK-NEXT: "DebugName": "main(int, char **)",
61+
// CHECK-NEXT: "DemoStat": "",
4862
// CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}",
4963
// CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}",
5064
// CHECK-NEXT: "MaxCFGSize": "{{[0-9]+}}",
@@ -102,3 +116,6 @@ int main(int argc, char **argv) {
102116
int i = non_entry_point(argc);
103117
return i;
104118
}
119+
120+
void func_one() {}
121+
void func_two() {}

0 commit comments

Comments
 (0)