10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 19 void FoldInitTypeCheck::registerMatchers(MatchFinder *Finder) {
22 const auto BuiltinTypeWithId = [](
const char *ID) {
23 return hasCanonicalType(builtinType().bind(ID));
25 const auto IteratorWithValueType = [&BuiltinTypeWithId](
const char *ID) {
28 pointsTo(BuiltinTypeWithId(ID)),
30 recordType(hasDeclaration(has(typedefNameDecl(
31 hasName(
"value_type"), hasType(BuiltinTypeWithId(ID)))))));
34 const auto IteratorParam = parmVarDecl(
35 hasType(hasCanonicalType(IteratorWithValueType(
"IterValueType"))));
36 const auto Iterator2Param = parmVarDecl(
37 hasType(hasCanonicalType(IteratorWithValueType(
"Iter2ValueType"))));
38 const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId(
"InitType")));
42 callExpr(callee(functionDecl(
43 hasAnyName(
"::std::accumulate",
"::std::reduce"),
44 hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
50 callExpr(callee(functionDecl(hasName(
"::std::inner_product"),
51 hasParameter(0, IteratorParam),
52 hasParameter(2, Iterator2Param),
53 hasParameter(3, InitParam))),
59 callExpr(callee(functionDecl(hasName(
"::std::reduce"),
60 hasParameter(1, IteratorParam),
61 hasParameter(3, InitParam))),
67 callExpr(callee(functionDecl(hasName(
"::std::inner_product"),
68 hasParameter(1, IteratorParam),
69 hasParameter(3, Iterator2Param),
70 hasParameter(4, InitParam))),
80 const BuiltinType &InitType,
81 const ASTContext &Context) {
82 const auto ValueTypeSize = Context.getTypeSize(&ValueType);
83 const auto InitTypeSize = Context.getTypeSize(&InitType);
86 if (ValueType.isFloatingPoint())
87 return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
92 if (ValueType.isInteger()) {
93 if (InitType.isInteger()) {
94 if (InitType.isSignedInteger() == ValueType.isSignedInteger())
95 return InitTypeSize >= ValueTypeSize;
96 return InitTypeSize > ValueTypeSize;
98 if (InitType.isFloatingPoint())
99 return InitTypeSize >= ValueTypeSize;
106 void FoldInitTypeCheck::doCheck(
const BuiltinType &IterValueType,
107 const BuiltinType &InitType,
108 const ASTContext &Context,
109 const CallExpr &CallNode) {
111 diag(CallNode.getExprLoc(),
"folding type %0 into type %1 might result in " 113 << IterValueType.desugar() << InitType.desugar();
117 void FoldInitTypeCheck::check(
const MatchFinder::MatchResult &Result) {
121 const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>(
"InitType");
122 const auto *IterValueType =
123 Result.Nodes.getNodeAs<BuiltinType>(
"IterValueType");
124 assert(InitType !=
nullptr);
125 assert(IterValueType !=
nullptr);
127 const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>(
"Call");
128 assert(CallNode !=
nullptr);
130 doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
132 if (
const auto *Iter2ValueType =
133 Result.Nodes.getNodeAs<BuiltinType>(
"Iter2ValueType"))
134 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.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//