C++: add support for C++17 fold expressions

This commit is contained in:
Nick Rolfe
2019-04-23 15:25:40 +01:00
parent 3905cf70f4
commit 4352a20be0
2 changed files with 66 additions and 0 deletions

View File

@@ -964,6 +964,65 @@ class NoExceptExpr extends Expr, @noexceptexpr {
}
}
/**
* A C++17 fold expression.
*/
class FoldExpr extends Expr, @foldexpr {
override string toString() {
exists(string op |
op = this.getOperatorString() and
if this.isUnaryFold()
then
if this.isLeftFold()
then result = "( ... " + op + " pack )"
else result = "( pack " + op + " ... )"
else
if this.isLeftFold()
then result = "( init " + op + " ... " + op + " pack )"
else result = "( pack " + op + " ... " + op + " init )"
)
}
/** Gets the binary operator used in this fold expression, as a string. */
string getOperatorString() { fold(underlyingElement(this), result, _) }
/** Holds if this is a left-fold expression. */
predicate isLeftFold() { fold(underlyingElement(this), _, true) }
/** Holds if this is a right-fold expression. */
predicate isRightFold() { fold(underlyingElement(this), _, false) }
/** Holds if this is a unary fold expression. */
predicate isUnaryFold() { getNumChild() = 1 }
/** Holds if this is a binary fold expression. */
predicate isBinaryFold() { getNumChild() = 2 }
/**
* Gets the child expression containing the unexpanded parameter pack.
*/
Expr getPackExpr() {
this.isUnaryFold() and
result = getChild(0)
or
this.isBinaryFold() and
if this.isRightFold() then result = getChild(0) else result = getChild(1)
}
/**
* If this is a binary fold, gets the expression representing the initial value.
*/
Expr getInitExpr() {
this.isBinaryFold() and
if this.isRightFold() then result = getChild(1) else result = getChild(0)
}
/**
* Holds if this is a binary fold with a child expression representing the initial value.
*/
predicate hasInitExpr() { exists(this.getInitExpr()) }
}
/**
* Holds if `child` is the `n`th child of `parent` in an alternative syntax
* tree that has `Conversion`s as part of the tree.

View File

@@ -1432,6 +1432,7 @@ case @expr.kind of
| 129 = @new_array_expr
// ... 130 @objc_array_literal deprecated
// ... 131 @objc_dictionary_literal deprecated
| 132 = @foldexpr
// ...
| 200 = @ctordirectinit
| 201 = @ctorvirtualinit
@@ -1579,6 +1580,12 @@ lambda_capture(
@addressable = @function | @variable ;
@accessible = @addressable | @enumconstant ;
fold(
int expr: @foldexpr ref,
string operator: string ref,
boolean is_left_fold: boolean ref
);
stmts(
unique int id: @stmt,
int kind: int ref,