diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..ea98d728 --- /dev/null +++ b/.clang-tidy @@ -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' diff --git a/src/DataTree.cc b/src/DataTree.cc index 5b3c2df0..b21e63c8 100644 --- a/src/DataTree.cc +++ b/src/DataTree.cc @@ -205,7 +205,7 @@ DataTree::AddPlus(expr_t iArg1, expr_t iArg2) // To treat commutativity of "+" // 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); return AddBinaryOp(iArg1, BinaryOpcode::plus, iArg2); } @@ -283,7 +283,7 @@ DataTree::AddTimes(expr_t iArg1, expr_t iArg2) // To treat commutativity of "*" // 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); return AddBinaryOp(iArg1, BinaryOpcode::times, iArg2); } diff --git a/src/DataTree.hh b/src/DataTree.hh index 93c2891f..7968e20c 100644 --- a/src/DataTree.hh +++ b/src/DataTree.hh @@ -431,7 +431,7 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int { try { - double argval = arg->eval({}); + double argval = arg->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage) double val = UnaryOpNode::eval_opcode(op_code, argval); 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 { - double argval1 = arg1->eval({}); - double argval2 = arg2->eval({}); + double argval1 = arg1->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage) + double argval2 = arg2->eval({}); // NOLINT(clang-analyzer-core.CallAndMessage) double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder); return AddPossiblyNegativeConstant(val); } diff --git a/src/ExprNode.cc b/src/ExprNode.cc index de8309d9..78cf5bba 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -3727,7 +3727,7 @@ UnaryOpNode::substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& if (vn) symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second, vn->symb_id, vn->lag); - else + else // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) symb_id = datatree.symbol_table.addDiffAuxiliaryVar(argsubst->idx, rit->second); // 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--) { if (i == last_index) + // NOLINTBEGIN(clang-analyzer-core.NullDereference) symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar(argsubst->idx, rit->second, last_aux_var->symb_id, -1); + // NOLINTEND(clang-analyzer-core.NullDereference) else symb_id = datatree.symbol_table.addDiffLagAuxiliaryVar( 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 subst_table[rit->second] + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) = dynamic_cast(aux_var->decreaseLeadsLags(base_index - rit->first)); assert(subst_table.contains(this)); @@ -5692,6 +5695,7 @@ BinaryOpNode::getPacAREC( vector, double>> linear_combination; try { + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) auto [vid, lag, pid, constant] = term->matchVariableTimesConstantTimesParam(true); linear_combination.emplace_back(vid.value(), lag, move(pid), constant); } @@ -5773,6 +5777,7 @@ BinaryOpNode::isParamTimesEndogExpr() const } else { + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) arg1->collectDynamicVariables(SymbolType::endogenous, endogs); arg1->collectDynamicVariables(SymbolType::exogenous, exogs); arg1->collectVariables(SymbolType::parameter, params); @@ -9311,6 +9316,7 @@ BinaryOpNode::matchEndogenousTimesConstant() const varg1 && varg1->get_type() == SymbolType::endogenous && arg2->isConstant()) return {varg1->symb_id, arg2}; if (auto varg2 = dynamic_cast(arg2); + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) varg2 && varg2->get_type() == SymbolType::endogenous && arg1->isConstant()) return {varg2->symb_id, arg1}; } diff --git a/src/ModelTree.cc b/src/ModelTree.cc index 6710c2bc..65671fe9 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -393,7 +393,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t& eval_context) const double val {[&] { try { - return d1->eval(eval_context); + return d1->eval(eval_context); // NOLINT(clang-analyzer-core.NullDereference) } catch (ExprNode::EvalExternalFunctionException& e) { diff --git a/src/ModelTree.hh b/src/ModelTree.hh index 2d361bbf..dc6f0378 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -751,6 +751,7 @@ ModelTree::writeTemporaryTerms(const temporary_terms_t& tt, temporary_terms_t& t if (dynamic_cast(it)) 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); output << " = "; it->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); diff --git a/src/Statement.cc b/src/Statement.cc index dc86196e..e8d568f2 100644 --- a/src/Statement.cc +++ b/src/Statement.cc @@ -184,6 +184,7 @@ OptionsList::writeOutput(ostream& output, const string& option_group) const void OptionsList::writeOutputCommon(ostream& output, const string& option_group) const { + // NOLINTBEGIN(clang-analyzer-core.CallAndMessage) for (const auto& [name, val] : options) std::visit( [&](const T& v) { @@ -261,6 +262,7 @@ OptionsList::writeOutputCommon(ostream& output, const string& option_group) cons } }, val); + // NOLINTEND(clang-analyzer-core.CallAndMessage) } void diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc index 13009c4a..00855263 100644 --- a/src/macro/Expressions.cc +++ b/src/macro/Expressions.cc @@ -623,12 +623,15 @@ Range::eval(Environment& env) const "the arguments must evaluate to reals"); vector arr; + // We do want a float counter, because that’s the macro-language semantics + // NOLINTBEGIN(clang-analyzer-security.FloatLoopCounter) if (*incdbl > 0 && *startdbl <= *enddbl) for (double i = *startdbl; i <= *enddbl; i += *incdbl) arr.emplace_back(make_shared(i)); else if (*startdbl >= *enddbl && *incdbl < 0) for (double i = *startdbl; i >= *enddbl; i += *incdbl) arr.emplace_back(make_shared(i)); + // NOLINTEND(clang-analyzer-security.FloatLoopCounter) return make_shared(arr, location); }