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 callExpr(callee(functionDecl(
56 hasAnyName(
"::std::accumulate",
"::std::reduce"),
57 hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
63 callExpr(callee(functionDecl(hasName(
"::std::inner_product"),
64 hasParameter(0, IteratorParam),
65 hasParameter(2, Iterator2Param),
66 hasParameter(3, InitParam))),
72 callExpr(callee(functionDecl(hasName(
"::std::reduce"),
73 hasParameter(1, IteratorParam),
74 hasParameter(3, InitParam))),
80 callExpr(callee(functionDecl(hasName(
"::std::inner_product"),
81 hasParameter(1, IteratorParam),
82 hasParameter(3, Iterator2Param),
83 hasParameter(4, InitParam))),
93 const BuiltinType &InitType,
94 const ASTContext &Context) {
95 const auto ValueTypeSize = Context.getTypeSize(&ValueType);
96 const auto InitTypeSize = Context.getTypeSize(&InitType);
99 if (ValueType.isFloatingPoint())
100 return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
105 if (ValueType.isInteger()) {
106 if (InitType.isInteger()) {
107 if (InitType.isSignedInteger() == ValueType.isSignedInteger())
108 return InitTypeSize >= ValueTypeSize;
109 return InitTypeSize > ValueTypeSize;
111 if (InitType.isFloatingPoint())
112 return InitTypeSize >= ValueTypeSize;
119void FoldInitTypeCheck::doCheck(
const BuiltinType &IterValueType,
134 const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>(
"InitType");
135 const auto *IterValueType =
136 Result.Nodes.getNodeAs<BuiltinType>(
"IterValueType");
137 assert(InitType !=
nullptr);
138 assert(IterValueType !=
nullptr);
140 const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>(
"Call");
141 assert(CallNode !=
nullptr);
143 doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
145 if (
const auto *Iter2ValueType =
146 Result.Nodes.getNodeAs<BuiltinType>(
"Iter2ValueType"))
147 doCheck(*Iter2ValueType, *InitType, *Result.Context, *CallNode);
static bool isValidBuiltinFold(const BuiltinType &ValueType, const BuiltinType &InitType, const ASTContext &Context)
Returns true if ValueType is allowed to fold into InitType, i.e.