---
# Conservative clang-tidy configuration for Eigen.
#
# Focuses on bug-finding checks with low false-positive rates.
# Intentionally omits blanket style enforcement (modernize-*, google-*,
# cppcoreguidelines-*) since Eigen has its own conventions and is a
# heavily-templated math library where many "modern C++" idioms don't apply.
# The individually named modernize-* checks below are the exceptions: they
# state actual Eigen conventions for new code. They only make sense because
# both entry points restrict diagnostics to the lines a change adds via
# --line-filter (ci/scripts/run-clang-tidy.sh for merge requests,
# scripts/clang_tidy_hook.py while editing); whole-file they would report
# thousands of pre-existing occurrences.

Checks: >
  -*,
  bugprone-*,
  modernize-use-nullptr,
  modernize-use-using,
  -bugprone-narrowing-conversions,
  -bugprone-easily-swappable-parameters,
  -bugprone-implicit-widening-of-multiplication-result,
  -bugprone-exception-escape,
  misc-redundant-expression,
  misc-unused-using-decls,
  misc-misleading-identifier,
  performance-for-range-copy,
  performance-implicit-conversion-in-loop,
  performance-unnecessary-copy-initialization,
  performance-unnecessary-value-param,
  readability-container-size-empty,
  readability-duplicate-include,
  readability-misleading-indentation,
  readability-redundant-control-flow,
  readability-redundant-smartptr-get,

WarningsAsErrors: ''

HeaderFilterRegex: 'Eigen/.*|test/.*|blas/.*|lapack/.*|unsupported/Eigen/.*'

# Eigen uses its own assert macros.
CheckOptions:
  - key: bugprone-assert-side-effect.AssertMacros
    value: 'eigen_assert,eigen_internal_assert,EIGEN_STATIC_ASSERT,VERIFY,VERIFY_IS_APPROX,VERIFY_IS_EQUAL,VERIFY_IS_MUCH_SMALLER_THAN,VERIFY_IS_NOT_APPROX,VERIFY_IS_NOT_EQUAL,VERIFY_IS_UNITARY,VERIFY_RAISES_ASSERT'

# Eigen-specific conventions that no upstream check covers, contributed in the
# review of !2775. `CustomChecks` requires clang-tidy >= 22, while the CI image
# (checkformat:clangtidy, Ubuntu 24.04) provides 18, so these are parked here
# rather than enabled; uncomment once that job's toolchain moves. Until then
# scripts/check_style.py reports the first three textually on added lines.
# CustomChecks:
#   - Name: eigen-bool-constant
#     Query: |
#       match typeLoc(loc(templateSpecializationType(
#         hasDeclaration(namedDecl(hasName("::std::integral_constant"))),
#         hasTemplateArgument(0, refersToType(booleanType())),
#       ))).bind("target")
#     Diagnostic:
#       - BindName: target
#         Message: use `Eigen::internal::bool_constant<_>` instead of `std::integral_constant<bool, _>`
#         Level: Warning
#   - Name: eigen-if-constexpr
#     Query: |
#       match ifStmt(
#         isConstexpr(),
#         unless(hasCondition(isExpandedFromMacro("EIGEN_IF_CONSTEXPR"))),
#       ).bind("target")
#     Diagnostic:
#       - BindName: target
#         Message: baseline is C++14; use `EIGEN_IF_CONSTEXPR (...)` with unconditionally-valid branches
#         Level: Warning
#   - Name: eigen-enum-constant
#     # Unnamed enums only — named class-scope enums are legitimate.  There is
#     # no isAnonymous() narrowing matcher for enum declarations, so the query
#     # matches the placeholder name Clang generates for them, resembling
#     # `::ns::(unnamed enum at File.h:12)` as of Clang 22, whose trailing `)`
#     # no real identifier can carry.
#     Query: |
#       match enumDecl(
#         hasDeclContext(cxxRecordDecl()),
#         matchesName("\\)$"),
#       ).bind("target")
#     Diagnostic:
#       - BindName: target
#         Message: use `static constexpr` instead of `enum` for class constants
#         Level: Warning
#   - Name: eigen-unsigned-flags
#     Query: |
#       match varDecl(
#         hasDeclContext(cxxRecordDecl()),
#         isStaticStorageClass(),
#         isConstexpr(),
#         matchesName("Flags0?"),
#         hasType(isSignedInteger()),
#       ).bind("target")
#     Diagnostic:
#       - BindName: target
#         Message: flag types are conventionally unsigned
#         Level: Warning
...
