20 const auto BuiltinTypeWithId = [](
const char *ID) {
21 return hasCanonicalType(builtinType().bind(ID));
23 const auto IteratorWithValueType = [&BuiltinTypeWithId](
const char *ID) {
26 pointsTo(BuiltinTypeWithId(ID)),
34 hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(has(functionDecl(
35 hasOverloadedOperatorName(
"*"),
36 returns(qualType(hasCanonicalType(anyOf(
38 references(BuiltinTypeWithId(ID)),
40 BuiltinTypeWithId(ID),
42 autoType(hasDeducedType(BuiltinTypeWithId(ID)))
47 const auto IteratorParam = parmVarDecl(
48 hasType(hasCanonicalType(IteratorWithValueType(
"IterValueType"))));
49 const auto Iterator2Param = parmVarDecl(
50 hasType(hasCanonicalType(IteratorWithValueType(
"Iter2ValueType"))));
51 const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId(
"InitType")));
55 const auto TransparentFunctor = expr(hasType(
56 hasCanonicalType(recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
57 "::std::plus",
"::std::minus",
"::std::multiplies",
"::std::divides",
58 "::std::bit_and",
"::std::bit_or",
"::std::bit_xor")))))));
63 callee(functionDecl(hasAnyName(
"::std::accumulate",
"::std::reduce"),
64 hasParameter(0, IteratorParam),
65 hasParameter(2, InitParam))),
66 anyOf(argumentCountIs(3),
67 allOf(argumentCountIs(4), hasArgument(3, TransparentFunctor))))
74 hasName(
"::std::inner_product"), hasParameter(0, IteratorParam),
75 hasParameter(2, Iterator2Param), hasParameter(3, InitParam))),
76 anyOf(argumentCountIs(4),
77 allOf(argumentCountIs(6), hasArgument(4, TransparentFunctor),
78 hasArgument(5, TransparentFunctor))))
84 callee(functionDecl(hasName(
"::std::reduce"),
85 hasParameter(1, IteratorParam),
86 hasParameter(3, InitParam))),
87 anyOf(argumentCountIs(4),
88 allOf(argumentCountIs(5), hasArgument(4, TransparentFunctor))))
95 hasName(
"::std::inner_product"), hasParameter(1, IteratorParam),
96 hasParameter(3, Iterator2Param), hasParameter(4, InitParam))),
97 anyOf(argumentCountIs(5),
98 allOf(argumentCountIs(7), hasArgument(5, TransparentFunctor),
99 hasArgument(6, TransparentFunctor))))
108 const BuiltinType &InitType,
109 const ASTContext &Context) {
110 const auto ValueTypeSize = Context.getTypeSize(&ValueType);
111 const auto InitTypeSize = Context.getTypeSize(&InitType);
114 if (ValueType.isFloatingPoint())
115 return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
120 if (ValueType.isInteger()) {
121 if (InitType.isInteger()) {
122 if (InitType.isSignedInteger() == ValueType.isSignedInteger())
123 return InitTypeSize >= ValueTypeSize;
124 return InitTypeSize > ValueTypeSize;
126 if (InitType.isFloatingPoint())
127 return InitTypeSize >= ValueTypeSize;
149 const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>(
"InitType");
150 const auto *IterValueType =
151 Result.Nodes.getNodeAs<BuiltinType>(
"IterValueType");
152 assert(InitType !=
nullptr);
153 assert(IterValueType !=
nullptr);
155 const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>(
"Call");
156 assert(CallNode !=
nullptr);
158 doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
160 if (
const auto *Iter2ValueType =
161 Result.Nodes.getNodeAs<BuiltinType>(
"Iter2ValueType"))
162 doCheck(*Iter2ValueType, *InitType, *Result.Context, *CallNode);