Repository: llvm/llvm-project
File: clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp (C++)

Code before:
        // care about.
        // Notes:
        //   - `operator*` can be in one of the bases of the iterator class.
        //   - this does not handle cases when the `operator*` is defined
        //     outside the iterator class.
        recordType(
            hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(has(functionDecl(
                hasOverloadedOperatorName("*"),
                returns(qualType(hasCanonicalType(anyOf(
                    // `value_type& operator*();`
                    references(BuiltinTypeWithId(ID)),
                    // `value_type operator*();`
                    BuiltinTypeWithId(ID),
                    // `auto operator*();`, `decltype(auto) operator*();`
                    autoType(hasDeducedType(BuiltinTypeWithId(ID)))
                    //
                    )))))))))));
  };

  const auto IteratorParam = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
  const auto Iterator2Param = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
  const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));

  // Transparent standard functors that preserve arithmetic conversion semantics
  const auto TransparentFunctor = expr(hasType(
      hasCanonicalType(recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
          "::std::plus", "::std::minus", "::std::multiplies", "::std::divides",
          "::std::bit_and", "::std::bit_or", "::std::bit_xor")))))));

  // std::accumulate, std::reduce.
  Finder->addMatcher(
      callExpr(
          callee(functionDecl(hasAnyName("::std::accumulate", "::std::reduce"),
                              hasParameter(0, IteratorParam),
                              hasParameter(2, InitParam))),
          anyOf(argumentCountIs(3),
                allOf(argumentCountIs(4), hasArgument(3, TransparentFunctor))))
          .bind("Call"),
      this);
  // std::inner_product.
  Finder->addMatcher(
      callExpr(
          callee(functionDecl(
              hasName("::std::inner_product"), hasParameter(0, IteratorParam),
              hasParameter(2, Iterator2Param), hasParameter(3, InitParam))),
          anyOf(argumentCountIs(4),
                allOf(argumentCountIs(6), hasArgument(4, TransparentFunctor),
                      hasArgument(5, TransparentFunctor))))
          .bind("Call"),

Review comment (suggestion):
```suggestion
  // Transparent standard functors that preserve arithmetic conversion semantics.
```

Code after:
        // care about.
        // Notes:
        //   - `operator*` can be in one of the bases of the iterator class.
        //   - this does not handle cases when the `operator*` is defined
        //     outside the iterator class.
        recordType(
            hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(has(functionDecl(
                hasOverloadedOperatorName("*"),
                returns(qualType(hasCanonicalType(anyOf(
                    // `value_type& operator*();`
                    references(BuiltinTypeWithId(ID)),
                    // `value_type operator*();`
                    BuiltinTypeWithId(ID),
                    // `auto operator*();`, `decltype(auto) operator*();`
                    autoType(hasDeducedType(BuiltinTypeWithId(ID)))
                    //
                    )))))))))));
  };

  const auto IteratorParam = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
  const auto Iterator2Param = parmVarDecl(
      hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
  const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));

  // Transparent standard functors that preserve arithmetic conversion
  // semantics.
  const auto TransparentFunctor = expr(hasType(
      hasCanonicalType(recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
          "::std::plus", "::std::minus", "::std::multiplies", "::std::divides",
          "::std::bit_and", "::std::bit_or", "::std::bit_xor")))))));

  // std::accumulate, std::reduce.
  Finder->addMatcher(
      callExpr(
          callee(functionDecl(hasAnyName("::std::accumulate", "::std::reduce"),
                              hasParameter(0, IteratorParam),
                              hasParameter(2, InitParam))),
          anyOf(argumentCountIs(3),
                allOf(argumentCountIs(4), hasArgument(3, TransparentFunctor))))
          .bind("Call"),
      this);
  // std::inner_product.
  Finder->addMatcher(
      callExpr(
          callee(functionDecl(
              hasName("::std::inner_product"), hasParameter(0, IteratorParam),
              hasParameter(2, Iterator2Param), hasParameter(3, InitParam))),
          anyOf(argumentCountIs(4),
                allOf(argumentCountIs(6), hasArgument(4, TransparentFunctor),
                      hasArgument(5, TransparentFunctor))))