[clang] [analyzer] Introduce per-entry-point statistics (PR #131175)
DonĂ¡t Nagy via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 14 03:55:50 PDT 2025
================
@@ -0,0 +1,201 @@
+//===- EntryPointStats.cpp ----------------------------------------------===//
+//
+// 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
+//
+//===--------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iterator>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+struct Registry {
+ std::vector<BoolEPStat *> BoolStats;
+ std::vector<CounterEPStat *> CounterStats;
+ std::vector<UnsignedMaxEPStat *> UnsignedMaxStats;
+ std::vector<UnsignedEPStat *> UnsignedStats;
+
+ bool IsLocked = false;
+
+ struct Snapshot {
+ const Decl *EntryPoint;
+ std::vector<bool> BoolStatValues;
+ std::vector<unsigned> UnsignedStatValues;
+
+ void dumpDynamicStatsAsCSV(llvm::raw_ostream &OS) const;
+ };
+
+ std::vector<Snapshot> Snapshots;
+};
+} // namespace
+
+static llvm::ManagedStatic<Registry> StatsRegistry;
+
+namespace {
+template <typename Callback> void enumerateStatVectors(const Callback &Fn) {
+ Fn(StatsRegistry->BoolStats);
+ Fn(StatsRegistry->CounterStats);
+ Fn(StatsRegistry->UnsignedMaxStats);
+ Fn(StatsRegistry->UnsignedStats);
+}
+} // namespace
+
+static void checkStatName(const EntryPointStat *M) {
+#ifdef NDEBUG
+ return;
+#endif // NDEBUG
+ constexpr std::array AllowedSpecialChars = {
+ '+', '-', '_', '=', ':', '(', ')', '@', '!', '~',
+ '$', '%', '^', '&', '*', '\'', ';', '<', '>', '/'};
+ for (unsigned char C : M->name()) {
+ if (!std::isalnum(C) && !llvm::is_contained(AllowedSpecialChars, C)) {
+ llvm::errs() << "Stat name \"" << M->name() << "\" contains character '"
+ << C << "' (" << static_cast<int>(C)
+ << ") that is not allowed.";
+ assert(false && "The Stat name contains unallowed character");
----------------
NagyDonat wrote:
I think it would be more elegant to use an `llvm_unreachable` with a dynamically generated string, as e.g. `CheckerManager::runCheckersForEvalCall` does:
```c++
std::string AssertionMessage = llvm::formatv(
"The '{0}' call has been already evaluated by the {1} checker, "
"while the {2} checker also tried to evaluate the same call. At "
"most one checker supposed to evaluate a call.",
toString(Call), evaluatorChecker,
EvalCallChecker.Checker->getName());
llvm_unreachable(AssertionMessage.c_str());
```
https://github.com/llvm/llvm-project/pull/131175
More information about the cfe-commits
mailing list