Add a clang-tidy configuration file

Also add some annotations to remove some false positives.

There remain some boost-related false positives, it’s unclear how to suppress
them.
master
Sébastien Villemot 2023-12-04 16:37:00 +01:00
parent b2e9ec205e
commit bffd68e0bf
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
8 changed files with 28 additions and 7 deletions

9
.clang-tidy Normal file
View File

@ -0,0 +1,9 @@
# TODO: add the following check families:
# - performance-*
# - bugprone-*
# - cppcoreguidelines-
# NB: as of clang-tidy 16, we get several false positives inside boost, notably this one:
# https://github.com/llvm/llvm-project/issues/40486
Checks: 'modernize-*,-modernize-use-trailing-return-type,-clang-diagnostic-unqualified-std-cast-call'

View File

@ -205,7 +205,7 @@ DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
// To treat commutativity of "+" // To treat commutativity of "+"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx && !no_commutativity) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, iArg2); swap(iArg1, iArg2);
return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2);
} }
@ -283,7 +283,7 @@ DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
// To treat commutativity of "*" // To treat commutativity of "*"
// Nodes iArg1 and iArg2 are sorted by index // Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx && !no_commutativity) if (iArg1->idx > iArg2->idx && !no_commutativity) // NOLINT(clang-analyzer-core.NullDereference)
swap(iArg1, iArg2); swap(iArg1, iArg2);
return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2); return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2);
} }

View File

@ -431,7 +431,7 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
{ {
try try
{ {
double argval = arg->eval({}); double argval = arg->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = UnaryOpNode::eval_opcode(op_code, argval); double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }
@ -460,8 +460,8 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
// Try to reduce to a constant // Try to reduce to a constant
try try
{ {
double argval1 = arg1->eval({}); double argval1 = arg1->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double argval2 = arg2->eval({}); double argval2 = arg2->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage)
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder); double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val); return AddPossiblyNegativeConstant(val);
} }

View File

@ -3727,7 +3727,7 @@ UnaryOpNode::substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t&
if (vn) if (vn)
symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second, symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second,
vn->symb_id, vn->lag); vn->symb_id, vn->lag);
else else // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second); symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second);
// make originating aux var & equation // make originating aux var & equation
@ -3745,8 +3745,10 @@ UnaryOpNode::substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t&
for (int i = last_index; i > rit->first; i--) for (int i = last_index; i > rit->first; i--)
{ {
if (i == last_index) if (i == last_index)
// NOLINTBEGIN(clang-analyzer-core.NullDereference)
symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar(argsubst->idx, rit->second, symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar(argsubst->idx, rit->second,
last_aux_var->symb_id, -1); last_aux_var->symb_id, -1);
// NOLINTEND(clang-analyzer-core.NullDereference)
else else
symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar( symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar(
new_aux_var->idx, rit->second, last_aux_var->symb_id, -1); new_aux_var->idx, rit->second, last_aux_var->symb_id, -1);
@ -3884,6 +3886,7 @@ UnaryOpNode::substituteUnaryOpNodes(const lag_equivalence_table_t& nodes,
} }
else else
subst_table[rit->second] subst_table[rit->second]
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
= dynamic_cast<VariableNode*>(aux_var->decreaseLeadsLags(base_index - rit->first)); = dynamic_cast<VariableNode*>(aux_var->decreaseLeadsLags(base_index - rit->first));
assert(subst_table.contains(this)); assert(subst_table.contains(this));
@ -5692,6 +5695,7 @@ BinaryOpNode::getPacAREC(
vector<tuple<int, int, optional<int>, double>> linear_combination; vector<tuple<int, int, optional<int>, double>> linear_combination;
try try
{ {
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
auto [vid, lag, pid, constant] = term->matchVariableTimesConstantTimesParam(true); auto [vid, lag, pid, constant] = term->matchVariableTimesConstantTimesParam(true);
linear_combination.emplace_back(vid.value(), lag, move(pid), constant); linear_combination.emplace_back(vid.value(), lag, move(pid), constant);
} }
@ -5773,6 +5777,7 @@ BinaryOpNode::isParamTimesEndogExpr() const
} }
else else
{ {
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
arg1->collectDynamicVariables(SymbolType::endogenous, endogs); arg1->collectDynamicVariables(SymbolType::endogenous, endogs);
arg1->collectDynamicVariables(SymbolType::exogenous, exogs); arg1->collectDynamicVariables(SymbolType::exogenous, exogs);
arg1->collectVariables(SymbolType::parameter, params); arg1->collectVariables(SymbolType::parameter, params);
@ -9311,6 +9316,7 @@ BinaryOpNode::matchEndogenousTimesConstant() const
varg1 && varg1->get_type() == SymbolType::endogenous && arg2->isConstant()) varg1 && varg1->get_type() == SymbolType::endogenous && arg2->isConstant())
return {varg1->symb_id, arg2}; return {varg1->symb_id, arg2};
if (auto varg2 = dynamic_cast<VariableNode*>(arg2); if (auto varg2 = dynamic_cast<VariableNode*>(arg2);
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
varg2 && varg2->get_type() == SymbolType::endogenous && arg1->isConstant()) varg2 && varg2->get_type() == SymbolType::endogenous && arg1->isConstant())
return {varg2->symb_id, arg1}; return {varg2->symb_id, arg1};
} }

View File

@ -393,7 +393,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t& eval_context) const
double val {[&] { double val {[&] {
try try
{ {
return d1->eval(eval_context); return d1->eval(eval_context); // NOLINT(clang-analyzer-core.NullDereference)
} }
catch (ExprNode::EvalExternalFunctionException& e) catch (ExprNode::EvalExternalFunctionException& e)
{ {

View File

@ -751,6 +751,7 @@ ModelTree::writeTemporaryTerms(const temporary_terms_t& tt, temporary_terms_t& t
if (dynamic_cast<AbstractExternalFunctionNode*>(it)) if (dynamic_cast<AbstractExternalFunctionNode*>(it))
it->writeExternalFunctionOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); it->writeExternalFunctionOutput(output, output_type, temp_term_union, tt_idxs, tef_terms);
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
it->writeOutput(output, output_type, tt, tt_idxs, tef_terms); it->writeOutput(output, output_type, tt, tt_idxs, tef_terms);
output << " = "; output << " = ";
it->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); it->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms);

View File

@ -184,6 +184,7 @@ OptionsList::writeOutput(ostream& output, const string& option_group) const
void void
OptionsList::writeOutputCommon(ostream& output, const string& option_group) const OptionsList::writeOutputCommon(ostream& output, const string& option_group) const
{ {
// NOLINTBEGIN(clang-analyzer-core.CallAndMessage)
for (const auto& [name, val] : options) for (const auto& [name, val] : options)
std::visit( std::visit(
[&]<class T>(const T& v) { [&]<class T>(const T& v) {
@ -261,6 +262,7 @@ OptionsList::writeOutputCommon(ostream& output, const string& option_group) cons
} }
}, },
val); val);
// NOLINTEND(clang-analyzer-core.CallAndMessage)
} }
void void

View File

@ -623,12 +623,15 @@ Range::eval(Environment& env) const
"the arguments must evaluate to reals"); "the arguments must evaluate to reals");
vector<ExpressionPtr> arr; vector<ExpressionPtr> arr;
// We do want a float counter, because thats the macro-language semantics
// NOLINTBEGIN(clang-analyzer-security.FloatLoopCounter)
if (*incdbl > 0 && *startdbl <= *enddbl) if (*incdbl > 0 && *startdbl <= *enddbl)
for (double i = *startdbl; i <= *enddbl; i += *incdbl) for (double i = *startdbl; i <= *enddbl; i += *incdbl)
arr.emplace_back(make_shared<Real>(i)); arr.emplace_back(make_shared<Real>(i));
else if (*startdbl >= *enddbl && *incdbl < 0) else if (*startdbl >= *enddbl && *incdbl < 0)
for (double i = *startdbl; i >= *enddbl; i += *incdbl) for (double i = *startdbl; i >= *enddbl; i += *incdbl)
arr.emplace_back(make_shared<Real>(i)); arr.emplace_back(make_shared<Real>(i));
// NOLINTEND(clang-analyzer-security.FloatLoopCounter)
return make_shared<Array>(arr, location); return make_shared<Array>(arr, location);
} }