courbet updated this revision to Diff 474520.
courbet added a comment.
fix typo
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D137782/new/
https://reviews.llvm.org/D137782
Files:
clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
clang-tools-extra/test/clang-tidy/checkers/bugprone/fold-init-type.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/fold-init-type.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/fold-init-type.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/fold-init-type.cpp
@@ -1,39 +1,67 @@
-// RUN: %check_clang_tidy %s bugprone-fold-init-type %t
+// RUN: %check_clang_tidy %s bugprone-fold-init-type -std=c++17 %t
namespace std {
template <class InputIt, class T>
-T accumulate(InputIt first, InputIt last, T init);
+T accumulate(InputIt first, InputIt last, T init) {
+ // When `InputIt::operator*` returns a deduced `auto` type that refers to a
+ // dependent type, the return type is deduced only if `InputIt::operator*`
+ // is instantiated. In practice this happens somewhere in the implementation
+ // of `accumulate`. For tests, do it here.
+ (void)*first;
+}
template <class InputIt, class T>
-T reduce(InputIt first, InputIt last, T init);
+T reduce(InputIt first, InputIt last, T init) { (void)*first; }
template <class ExecutionPolicy, class InputIt, class T>
T reduce(ExecutionPolicy &&policy,
- InputIt first, InputIt last, T init);
+ InputIt first, InputIt last, T init) { (void)*first; }
struct parallel_execution_policy {};
constexpr parallel_execution_policy par{};
template <class InputIt1, class InputIt2, class T>
T inner_product(InputIt1 first1, InputIt1 last1,
- InputIt2 first2, T value);
+ InputIt2 first2, T value) { (void)*first1; (void)*first2; }
template <class ExecutionPolicy, class InputIt1, class InputIt2, class T>
T inner_product(ExecutionPolicy &&policy, InputIt1 first1, InputIt1 last1,
- InputIt2 first2, T value);
+ InputIt2 first2, T value) { (void)*first1; (void)*first2; }
} // namespace std
struct FloatIterator {
- typedef float value_type;
+ const float &operator*() const;
};
+
+struct DerivedFloatIterator : public FloatIterator {
+};
+
+template <typename ValueType> struct ByValueTemplateIterator {
+ ValueType operator*() const;
+};
+
+template <typename ValueType> struct ByRefTemplateIterator {
+ ValueType &operator*();
+};
+
+template <typename ValueType> struct ByRefTemplateIteratorWithAlias {
+ using reference = const ValueType&;
+ reference operator*();
+};
+
+template <typename ValueType> struct AutoByValueTemplateIterator {
+ auto operator*() const { return ValueType{}; }
+};
+
+template <typename ValueType> struct AutoByRefTemplateIterator {
+ decltype(auto) operator*() const { return value_; }
+ ValueType value_;
+};
+
template <typename ValueType>
-struct TypedefTemplateIterator { typedef ValueType value_type; };
-template <typename ValueType>
-struct UsingTemplateIterator { using value_type = ValueType; };
-template <typename ValueType>
-struct DependentTypedefTemplateIterator { typedef typename ValueType::value_type value_type; };
-template <typename ValueType>
-struct DependentUsingTemplateIterator : public TypedefTemplateIterator<ValueType> { using typename TypedefTemplateIterator<ValueType>::value_type; };
+struct InheritingByConstRefTemplateIterator
+ : public ByRefTemplateIterator<const ValueType> {};
+
using TypedeffedIterator = FloatIterator;
// Positives.
@@ -51,39 +79,57 @@
}
int accumulatePositive3() {
+ DerivedFloatIterator it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
+}
+
+int accumulatePositive4() {
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<unsigned> it;
+int accumulatePositive5() {
+ ByValueTemplateIterator<unsigned> it;
return std::accumulate(it, it, 0);
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
}
-int accumulatePositive5() {
- UsingTemplateIterator<unsigned> it;
+int accumulatePositive6() {
+ ByRefTemplateIterator<unsigned> it;
return std::accumulate(it, it, 0);
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
}
-int accumulatePositive6() {
- DependentTypedefTemplateIterator<UsingTemplateIterator<unsigned>> it;
+int accumulatePositive7() {
+ AutoByValueTemplateIterator<unsigned> it;
return std::accumulate(it, it, 0);
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
}
-int accumulatePositive7() {
+int accumulatePositive8() {
TypedeffedIterator it;
return std::accumulate(it, it, 0);
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'float' into type 'int'
}
-int accumulatePositive8() {
- DependentUsingTemplateIterator<unsigned> it;
+int accumulatePositive9() {
+ InheritingByConstRefTemplateIterator<unsigned> it;
return std::accumulate(it, it, 0);
- // FIXME: this one should trigger too.
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive10() {
+ AutoByRefTemplateIterator<unsigned> it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
+}
+
+int accumulatePositive11() {
+ ByRefTemplateIteratorWithAlias<unsigned> it;
+ return std::accumulate(it, it, 0);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: folding type 'unsigned int' into type 'int'
}
int reducePositive1() {
@@ -133,7 +179,7 @@
}
int negative4() {
- TypedefTemplateIterator<unsigned> it;
+ ByValueTemplateIterator<unsigned> it;
// For now this is OK.
return std::accumulate(it, it, 0.0);
}
@@ -156,3 +202,4 @@
return std::accumulate(a, a + 1, 0);
}
}
+
Index: clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.cpp
@@ -26,9 +26,24 @@
return anyOf(
// Pointer types.
pointsTo(BuiltinTypeWithId(ID)),
- // Iterator types.
- recordType(hasDeclaration(has(typedefNameDecl(
- hasName("value_type"), hasType(BuiltinTypeWithId(ID)))))));
+ // Iterator types have an `operator*` whose return type is the type we
+ // 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("*"),
+ anyOf(
+ // `value_type& operator*();`
+ returns(hasCanonicalType(
+ referenceType(pointee(BuiltinTypeWithId(ID))))),
+ // `value_type operator*();`
+ returns(hasCanonicalType(BuiltinTypeWithId(ID))),
+ // `auto operator*();`, `decltype(auto) operator*();`
+ returns(hasCanonicalType(autoType(
+ hasDeducedType(BuiltinTypeWithId(ID)))))))))))));
};
const auto IteratorParam = parmVarDecl(
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits