// RUN: %check_clang_tidy %s bugprone-fold-init-type %t namespace std { template T accumulate(InputIt first, InputIt last, T init); template T reduce(InputIt first, InputIt last, T init); template T reduce(ExecutionPolicy &&policy, InputIt first, InputIt last, T init); struct parallel_execution_policy {}; constexpr parallel_execution_policy par{}; template T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T value); template T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1, InputIt2 first2, T value); } // namespace std struct FloatIterator { typedef float value_type; }; template struct TypedefTemplateIterator { typedef ValueType value_type; }; template struct UsingTemplateIterator { using value_type = ValueType; }; template struct DependentTypedefTemplateIterator { typedef typename ValueType::value_type value_type; }; template struct DependentUsingTemplateIterator : public TypedefTemplateIterator { using typename TypedefTemplateIterator::value_type; }; using TypedeffedIterator = FloatIterator; // Positives. int accumulatePositive1() { float a[1] = {0.5f}; return std::accumulate(a, a + 1, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int accumulatePositive2() { FloatIterator it; return std::accumulate(it, it, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int accumulatePositive3() { double a[1] = {0.0}; return std::accumulate(a, a + 1, 0.0f); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'double' into type 'float' } int accumulatePositive4() { TypedefTemplateIterator it; return std::accumulate(it, it, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' } int accumulatePositive5() { UsingTemplateIterator it; return std::accumulate(it, it, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' } int accumulatePositive6() { DependentTypedefTemplateIterator> it; return std::accumulate(it, it, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int' } int accumulatePositive7() { TypedeffedIterator it; return std::accumulate(it, it, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int accumulatePositive8() { DependentUsingTemplateIterator it; return std::accumulate(it, it, 0); // FIXME: this one should trigger too. } int reducePositive1() { float a[1] = {0.5f}; return std::reduce(a, a + 1, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int reducePositive2() { float a[1] = {0.5f}; return std::reduce(std::par, a, a + 1, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int innerProductPositive1() { float a[1] = {0.5f}; int b[1] = {1}; return std::inner_product(std::par, a, a + 1, b, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } int innerProductPositive2() { float a[1] = {0.5f}; int b[1] = {1}; return std::inner_product(std::par, a, a + 1, b, 0); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int' } // Negatives. int negative1() { float a[1] = {0.5f}; // This is OK because types match. return std::accumulate(a, a + 1, 0.0); } int negative2() { float a[1] = {0.5f}; // This is OK because double is bigger than float. return std::accumulate(a, a + 1, 0.0); } int negative3() { float a[1] = {0.5f}; // This is OK because the user explicitly specified T. return std::accumulate(a, a + 1, 0); } int negative4() { TypedefTemplateIterator it; // For now this is OK. return std::accumulate(it, it, 0.0); } int negative5() { float a[1] = {0.5f}; float b[1] = {1.0f}; return std::inner_product(std::par, a, a + 1, b, 0.0f); } namespace blah { namespace std { template T accumulate(InputIt, InputIt, T); // We should not care about this one. } int negative5() { float a[1] = {0.5f}; // Note that this is using blah::std::accumulate. return std::accumulate(a, a + 1, 0); } }