Skip to content

Commit 06c4184

Browse files
committed
Make the analysis option a Positive value
1 parent 7dc6f31 commit 06c4184

File tree

7 files changed

+70
-16
lines changed

7 files changed

+70
-16
lines changed

clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#ifndef LLVM_ADT_STRINGREF_H
13+
#if !defined(LLVM_ADT_STRINGREF_H) || !defined(LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H)
1414
#error This .def file is expected to be included in translation units where \
15-
"llvm/ADT/StringRef.h" is already included!
15+
"llvm/ADT/StringRef.h" and "clang/StaticAnalyzer/Core/AnalyzerOptions.h" are \
16+
already included!
1617
#endif
1718

1819
#ifdef ANALYZER_OPTION
@@ -216,13 +217,13 @@ ANALYZER_OPTION(
216217
"hardware. Set 0 for unlimited.", 0)
217218

218219
ANALYZER_OPTION(
219-
unsigned, Z3CrosscheckRetriesOnTimeout,
220-
"crosscheck-with-z3-retries-on-timeout",
221-
"Set how many times the oracle is allowed to retry a Z3 query. "
222-
"Set 0 for not allowing retries, in which case each Z3 query would be "
223-
"attempted only once. Increasing the number of retries is often more "
224-
"effective at reducing the number of nondeterministic diagnostics than "
225-
"\"crosscheck-with-z3-timeout-threshold\" in practice.", 2)
220+
PositiveAnalyzerOption, Z3CrosscheckMaxAttemptsPerQuery,
221+
"crosscheck-with-z3-max-attempts-per-query",
222+
"Set how many times the oracle is allowed to run a Z3 query. "
223+
"This must be a positive value. Set 1 to not allow any retry attempts. "
224+
"Increasing the number of attempts is often more effective at reducing "
225+
"the number of nondeterministic diagnostics than "
226+
"\"crosscheck-with-z3-timeout-threshold\" in practice.", 3)
226227

227228
ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile,
228229
"report-in-main-source-file",

clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,31 @@ enum UserModeKind {
124124

125125
enum class CTUPhase1InliningKind { None, Small, All };
126126

127+
class PositiveAnalyzerOption {
128+
public:
129+
PositiveAnalyzerOption() = default;
130+
PositiveAnalyzerOption(const PositiveAnalyzerOption &) = default;
131+
PositiveAnalyzerOption &operator=(const PositiveAnalyzerOption &) = default;
132+
133+
static std::optional<PositiveAnalyzerOption> create(unsigned Val) {
134+
if (Val == 0)
135+
return std::nullopt;
136+
return PositiveAnalyzerOption{Val};
137+
}
138+
static std::optional<PositiveAnalyzerOption> create(StringRef Str) {
139+
unsigned Parsed = 0;
140+
if (Str.getAsInteger(0, Parsed))
141+
return std::nullopt;
142+
return PositiveAnalyzerOption::create(Parsed);
143+
}
144+
operator unsigned() const { return Value; }
145+
146+
private:
147+
explicit constexpr PositiveAnalyzerOption(unsigned Value) : Value(Value) {}
148+
149+
unsigned Value = 1;
150+
};
151+
127152
/// Stores options for the analyzer from the command line.
128153
///
129154
/// Some options are frontend flags (e.g.: -analyzer-output), but some are

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,25 @@ static void initOption(AnalyzerOptions::ConfigTable &Config,
12601260
<< Name << "an unsigned";
12611261
}
12621262

1263+
static void initOption(AnalyzerOptions::ConfigTable &Config,
1264+
DiagnosticsEngine *Diags,
1265+
PositiveAnalyzerOption &OptionField, StringRef Name,
1266+
unsigned DefaultVal) {
1267+
auto Parsed = PositiveAnalyzerOption::create(
1268+
getStringOption(Config, Name, std::to_string(DefaultVal)));
1269+
if (Parsed.has_value()) {
1270+
OptionField = Parsed.value();
1271+
return;
1272+
}
1273+
if (Diags && !Parsed.has_value())
1274+
Diags->Report(diag::err_analyzer_config_invalid_input)
1275+
<< Name << "a positive";
1276+
1277+
auto Default = PositiveAnalyzerOption::create(DefaultVal);
1278+
assert(Default.has_value());
1279+
OptionField = Default.value();
1280+
}
1281+
12631282
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
12641283
DiagnosticsEngine *Diags) {
12651284
// TODO: There's no need to store the entire configtable, it'd be plenty

clang/lib/StaticAnalyzer/Core/Z3CrosscheckVisitor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
#define DEBUG_TYPE "Z3CrosscheckOracle"
2323

24-
// Queries retried at most `Z3CrosscheckRetriesOnTimeout` number of times if the
25-
// `check()` call returns `UNDEF` for any reason. Each query is only counted
24+
// Queries retried at most `Z3CrosscheckMaxAttemptsPerQuery` number of times if
25+
// the `check()` call returns `UNDEF` for any reason. Each query is only counted
2626
// once for these statistics, the retries are not accounted for.
2727
STATISTIC(NumZ3QueriesDone, "Number of Z3 queries done");
2828
STATISTIC(NumTimesZ3TimedOut, "Number of times Z3 query timed out");
@@ -99,7 +99,7 @@ void Z3CrosscheckVisitor::finalizeVisitor(BugReporterContext &BRC,
9999

100100
// And check for satisfiability
101101
unsigned MinQueryTimeAcrossAttempts = std::numeric_limits<unsigned>::max();
102-
for (unsigned I = 0; I <= Opts.Z3CrosscheckRetriesOnTimeout; ++I) {
102+
for (unsigned I = 0; I <= Opts.Z3CrosscheckMaxAttemptsPerQuery; ++I) {
103103
Result = AttemptOnce(RefutationSolver);
104104
Result.Z3QueryTimeMilliseconds =
105105
std::min(MinQueryTimeAcrossAttempts, Result.Z3QueryTimeMilliseconds);

clang/test/Analysis/analyzer-config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
// CHECK-NEXT: cplusplus.SmartPtrModeling:ModelSmartPtrDereference = false
4242
// CHECK-NEXT: crosscheck-with-z3 = false
4343
// CHECK-NEXT: crosscheck-with-z3-eqclass-timeout-threshold = 0
44-
// CHECK-NEXT: crosscheck-with-z3-retries-on-timeout = 2
44+
// CHECK-NEXT: crosscheck-with-z3-max-attempts-per-query = 3
4545
// CHECK-NEXT: crosscheck-with-z3-rlimit-threshold = 0
4646
// CHECK-NEXT: crosscheck-with-z3-timeout-threshold = 15000
4747
// CHECK-NEXT: ctu-dir = ""

clang/test/Analysis/z3-crosscheck-retry.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Check the default config.
22
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ConfigDumper 2>&1 \
33
// RUN: | FileCheck %s --match-full-lines
4-
// CHECK: crosscheck-with-z3-retries-on-timeout = 2
4+
// CHECK: crosscheck-with-z3-max-attempts-per-query = 3
55

66
// RUN: rm -rf %t && mkdir %t
77
// RUN: %host_cxx -shared -fPIC \
@@ -14,7 +14,7 @@
1414
// DEFINE: -analyzer-config crosscheck-with-z3=true \
1515
// DEFINE: -analyzer-checker=core
1616

17-
// DEFINE: %{retry} = -analyzer-config crosscheck-with-z3-retries-on-timeout
17+
// DEFINE: %{retry} = -analyzer-config crosscheck-with-z3-max-attempts-per-query
1818

1919
// RUN: Z3_SOLVER_RESULTS="UNDEF" %{mocked_clang} %{retry}=0 -verify=refuted
2020
// RUN: Z3_SOLVER_RESULTS="UNSAT" %{mocked_clang} %{retry}=0 -verify=refuted

clang/unittests/StaticAnalyzer/Z3CrosscheckOracleTest.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,22 @@ static constexpr std::optional<bool> UNDEF = std::nullopt;
2727
static unsigned operator""_ms(unsigned long long ms) { return ms; }
2828
static unsigned operator""_step(unsigned long long rlimit) { return rlimit; }
2929

30+
template <class Ret, class Arg> static Ret makeDefaultOption(Arg Value) {
31+
return Value;
32+
}
33+
template <> PositiveAnalyzerOption makeDefaultOption(int Value) {
34+
auto DefaultVal = PositiveAnalyzerOption::create(Value);
35+
assert(DefaultVal.has_value());
36+
return DefaultVal.value();
37+
}
38+
3039
static const AnalyzerOptions DefaultOpts = [] {
3140
AnalyzerOptions Config;
3241
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
3342
SHALLOW_VAL, DEEP_VAL) \
3443
ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEEP_VAL)
3544
#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
36-
Config.NAME = DEFAULT_VAL;
45+
Config.NAME = makeDefaultOption<TYPE>(DEFAULT_VAL);
3746
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
3847

3948
// Remember to update the tests in this file when these values change.

0 commit comments

Comments
 (0)