diff options
author | Yuao Ma <c8ef@outlook.com> | 2025-09-12 20:28:19 +0800 |
---|---|---|
committer | c8ef <c8ef@outlook.com> | 2025-09-14 18:24:50 +0800 |
commit | af53cfeb8352b18cbc0684f04c5106db20142f7b (patch) | |
tree | 3de0e72cacf6f091a6a6c85f4e76ffc1c486eab6 | |
parent | 21d1bb1922fa7cd98f2a27d002e48b488e772176 (diff) | |
download | gcc-af53cfeb8352b18cbc0684f04c5106db20142f7b.zip gcc-af53cfeb8352b18cbc0684f04c5106db20142f7b.tar.gz gcc-af53cfeb8352b18cbc0684f04c5106db20142f7b.tar.bz2 |
fortran: implement conditional expression for fortran 2023
This patch adds support for conditional expressions in Fortran 2023 for a
limited set of types (logical, numerical), and also includes limited support
for conditional arguments without `.nil.` support.
gcc/fortran/ChangeLog:
* dump-parse-tree.cc (show_expr): Add support for EXPR_CONDITIONAL.
* expr.cc (gfc_get_conditional_expr): Add cond-expr constructor.
(gfc_copy_expr, free_expr0, gfc_is_constant_expr,
simplify_conditional, gfc_simplify_expr, gfc_check_init_expr,
check_restricted, gfc_traverse_expr): Add support for EXPR_CONDITIONAL.
* frontend-passes.cc (gfc_expr_walker): Ditto.
* gfortran.h (enum expr_t): Add EXPR_CONDITIONAL.
(gfc_get_operator_expr): Format fix.
(gfc_get_conditional_expr): New decl.
* matchexp.cc
(match_conditional, match_primary): Parsing for EXPR_CONDITIONAL.
* module.cc (mio_expr): Add support for EXPR_CONDITIONAL.
* resolve.cc (resolve_conditional, gfc_resolve_expr): Ditto.
* trans-array.cc (gfc_walk_conditional_expr, gfc_walk_subexpr): Ditto.
* trans-expr.cc
(gfc_conv_conditional_expr): Codegen for EXPR_CONDITIONAL.
(gfc_apply_interface_mapping_to_expr, gfc_conv_expr,
gfc_conv_expr_reference): Add support for EXPR_CONDITIONAL.
gcc/testsuite/ChangeLog:
* gfortran.dg/conditional_1.f90: New test.
* gfortran.dg/conditional_2.f90: New test.
* gfortran.dg/conditional_3.f90: New test.
* gfortran.dg/conditional_4.f90: New test.
* gfortran.dg/conditional_5.f90: New test.
* gfortran.dg/conditional_6.f90: New test.
* gfortran.dg/conditional_7.f90: New test.
* gfortran.dg/conditional_8.f90: New test.
* gfortran.dg/conditional_9.f90: New test.
-rw-r--r-- | gcc/fortran/dump-parse-tree.cc | 10 | ||||
-rw-r--r-- | gcc/fortran/expr.cc | 118 | ||||
-rw-r--r-- | gcc/fortran/frontend-passes.cc | 5 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 30 | ||||
-rw-r--r-- | gcc/fortran/matchexp.cc | 79 | ||||
-rw-r--r-- | gcc/fortran/module.cc | 10 | ||||
-rw-r--r-- | gcc/fortran/resolve.cc | 71 | ||||
-rw-r--r-- | gcc/fortran/trans-array.cc | 13 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.cc | 70 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_1.f90 | 32 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_2.f90 | 13 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_3.f90 | 9 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_4.f90 | 21 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_5.f90 | 7 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_6.f90 | 16 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_7.f90 | 11 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_8.f90 | 14 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/conditional_9.f90 | 11 |
18 files changed, 522 insertions, 18 deletions
diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 3cd2eee..eda0659 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -767,6 +767,16 @@ show_expr (gfc_expr *p) break; + case EXPR_CONDITIONAL: + fputc ('(', dumpfile); + show_expr (p->value.conditional.condition); + fputs (" ? ", dumpfile); + show_expr (p->value.conditional.true_expr); + fputs (" : ", dumpfile); + show_expr (p->value.conditional.false_expr); + fputc (')', dumpfile); + break; + case EXPR_COMPCALL: show_compcall (p); break; diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 3dbf8cb..a11ff79 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -116,6 +116,25 @@ gfc_get_operator_expr (locus *where, gfc_intrinsic_op op, return e; } +/* Get a new expression node that is an conditional expression node. */ + +gfc_expr * +gfc_get_conditional_expr (locus *where, gfc_expr *condition, + gfc_expr *true_expr, gfc_expr *false_expr) +{ + gfc_expr *e; + + e = gfc_get_expr (); + e->expr_type = EXPR_CONDITIONAL; + e->value.conditional.condition = condition; + e->value.conditional.true_expr = true_expr; + e->value.conditional.false_expr = false_expr; + + if (where) + e->where = *where; + + return e; +} /* Get a new expression node that is an structure constructor of given type and kind. */ @@ -393,6 +412,15 @@ gfc_copy_expr (gfc_expr *p) break; + case EXPR_CONDITIONAL: + q->value.conditional.condition + = gfc_copy_expr (p->value.conditional.condition); + q->value.conditional.true_expr + = gfc_copy_expr (p->value.conditional.true_expr); + q->value.conditional.false_expr + = gfc_copy_expr (p->value.conditional.false_expr); + break; + case EXPR_FUNCTION: q->value.function.actual = gfc_copy_actual_arglist (p->value.function.actual); @@ -502,6 +530,12 @@ free_expr0 (gfc_expr *e) gfc_free_expr (e->value.op.op2); break; + case EXPR_CONDITIONAL: + gfc_free_expr (e->value.conditional.condition); + gfc_free_expr (e->value.conditional.true_expr); + gfc_free_expr (e->value.conditional.false_expr); + break; + case EXPR_FUNCTION: gfc_free_actual_arglist (e->value.function.actual); break; @@ -1083,6 +1117,11 @@ gfc_is_constant_expr (gfc_expr *e) && (e->value.op.op2 == NULL || gfc_is_constant_expr (e->value.op.op2))); + case EXPR_CONDITIONAL: + return gfc_is_constant_expr (e->value.conditional.condition) + && gfc_is_constant_expr (e->value.conditional.true_expr) + && gfc_is_constant_expr (e->value.conditional.false_expr); + case EXPR_VARIABLE: /* The only context in which this can occur is in a parameterized derived type declaration, so returning true is OK. */ @@ -1354,6 +1393,43 @@ simplify_intrinsic_op (gfc_expr *p, int type) return true; } +/* Try to collapse conditional expressions. */ + +static bool +simplify_conditional (gfc_expr *p, int type) +{ + gfc_expr *condition, *true_expr, *false_expr; + + condition = p->value.conditional.condition; + true_expr = p->value.conditional.true_expr; + false_expr = p->value.conditional.false_expr; + + if (!gfc_simplify_expr (condition, type) + || !gfc_simplify_expr (true_expr, type) + || !gfc_simplify_expr (false_expr, type)) + return false; + + if (!gfc_is_constant_expr (condition)) + return true; + + p->value.conditional.condition = NULL; + p->value.conditional.true_expr = NULL; + p->value.conditional.false_expr = NULL; + + if (condition->value.logical) + { + gfc_replace_expr (p, true_expr); + gfc_free_expr (false_expr); + } + else + { + gfc_replace_expr (p, false_expr); + gfc_free_expr (true_expr); + } + gfc_free_expr (condition); + + return true; +} /* Subroutine to simplify constructor expressions. Mutually recursive with gfc_simplify_expr(). */ @@ -2459,6 +2535,11 @@ gfc_simplify_expr (gfc_expr *p, int type) return false; break; + case EXPR_CONDITIONAL: + if (!simplify_conditional (p, type)) + return false; + break; + case EXPR_VARIABLE: /* Only substitute array parameter variables if we are in an initialization expression, or we want a subsection. */ @@ -3133,6 +3214,20 @@ gfc_check_init_expr (gfc_expr *e) break; + case EXPR_CONDITIONAL: + t = gfc_check_init_expr (e->value.conditional.condition); + if (!t) + break; + t = gfc_check_init_expr (e->value.conditional.true_expr); + if (!t) + break; + t = gfc_check_init_expr (e->value.conditional.false_expr); + if (t) + t = gfc_simplify_expr (e, 0); + else + t = false; + break; + case EXPR_FUNCTION: t = false; @@ -3609,6 +3704,20 @@ check_restricted (gfc_expr *e) break; + case EXPR_CONDITIONAL: + t = check_restricted (e->value.conditional.condition); + if (!t) + break; + t = check_restricted (e->value.conditional.true_expr); + if (!t) + break; + t = check_restricted (e->value.conditional.false_expr); + if (t) + t = gfc_simplify_expr (e, 0); + else + t = false; + break; + case EXPR_FUNCTION: if (e->value.function.esym) { @@ -5700,6 +5809,15 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym, return true; break; + case EXPR_CONDITIONAL: + if (gfc_traverse_expr (expr->value.conditional.condition, sym, func, f)) + return true; + if (gfc_traverse_expr (expr->value.conditional.true_expr, sym, func, f)) + return true; + if (gfc_traverse_expr (expr->value.conditional.false_expr, sym, func, f)) + return true; + break; + default: gcc_unreachable (); break; diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc index 02a0a23..4a468b9 100644 --- a/gcc/fortran/frontend-passes.cc +++ b/gcc/fortran/frontend-passes.cc @@ -5218,6 +5218,11 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data) for (a = (*e)->value.function.actual; a; a = a->next) WALK_SUBEXPR (a->expr); break; + case EXPR_CONDITIONAL: + WALK_SUBEXPR ((*e)->value.conditional.condition); + WALK_SUBEXPR ((*e)->value.conditional.true_expr); + WALK_SUBEXPR ((*e)->value.conditional.false_expr); + break; case EXPR_COMPCALL: case EXPR_PPC: WALK_SUBEXPR ((*e)->value.compcall.base_object); diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 482031d..2e6b368 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -176,8 +176,19 @@ enum gfc_source_form /* Expression node types. */ enum expr_t - { EXPR_UNKNOWN = 0, EXPR_OP = 1, EXPR_FUNCTION, EXPR_CONSTANT, EXPR_VARIABLE, - EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL, EXPR_COMPCALL, EXPR_PPC +{ + EXPR_UNKNOWN = 0, + EXPR_OP = 1, + EXPR_FUNCTION, + EXPR_CONSTANT, + EXPR_VARIABLE, + EXPR_SUBSTRING, + EXPR_STRUCTURE, + EXPR_ARRAY, + EXPR_NULL, + EXPR_COMPCALL, + EXPR_PPC, + EXPR_CONDITIONAL, }; /* Array types. */ @@ -2809,8 +2820,14 @@ typedef struct gfc_expr character; gfc_constructor_base constructor; - } - value; + + struct + { + struct gfc_expr *condition; + struct gfc_expr *true_expr; + struct gfc_expr *false_expr; + } conditional; + } value; /* Used to store PDT expression lists associated with expressions. */ gfc_actual_arglist *param_list; @@ -3925,7 +3942,10 @@ bool gfc_is_ptr_fcn (gfc_expr *); gfc_expr *gfc_get_expr (void); gfc_expr *gfc_get_array_expr (bt type, int kind, locus *); gfc_expr *gfc_get_null_expr (locus *); -gfc_expr *gfc_get_operator_expr (locus *, gfc_intrinsic_op,gfc_expr *, gfc_expr *); +gfc_expr *gfc_get_operator_expr (locus *, gfc_intrinsic_op, gfc_expr *, + gfc_expr *); +gfc_expr *gfc_get_conditional_expr (locus *, gfc_expr *, gfc_expr *, + gfc_expr *); gfc_expr *gfc_get_structure_constructor_expr (bt, int, locus *); gfc_expr *gfc_get_constant_expr (bt, int, locus *); gfc_expr *gfc_get_character_expr (int, locus *, const char *, gfc_charlen_t len); diff --git a/gcc/fortran/matchexp.cc b/gcc/fortran/matchexp.cc index 9b66243..e3a9925 100644 --- a/gcc/fortran/matchexp.cc +++ b/gcc/fortran/matchexp.cc @@ -138,6 +138,65 @@ gfc_get_parentheses (gfc_expr *e) return e2; } +/* Match a conditional expression. */ + +static match +match_conditional (gfc_expr **result) +{ + gfc_expr *condition, *true_expr, *false_expr; + locus where; + match m; + + where = gfc_current_locus; + + m = gfc_match_expr (&condition); + if (m != MATCH_YES) + { + gfc_error (expression_syntax); + return MATCH_ERROR; + } + + m = gfc_match_char ('?'); + if (m != MATCH_YES) + { + *result = condition; + return MATCH_YES; + } + else if (!gfc_notify_std (GFC_STD_F2023, "Conditional expression at %L", + &where)) + { + gfc_free_expr (condition); + return MATCH_ERROR; + } + + gfc_gobble_whitespace (); + m = gfc_match_expr (&true_expr); + if (m != MATCH_YES) + { + gfc_free_expr (condition); + return m; + } + + m = gfc_match_char (':'); + if (m != MATCH_YES) + { + gfc_error ("Expected ':' in conditional expression at %C"); + gfc_free_expr (condition); + gfc_free_expr (true_expr); + return MATCH_ERROR; + } + + m = match_conditional (&false_expr); + if (m != MATCH_YES) + { + gfc_free_expr (condition); + gfc_free_expr (true_expr); + return m; + } + + *result = gfc_get_conditional_expr (&where, condition, true_expr, false_expr); + return MATCH_YES; +} /* Match a primary expression. */ @@ -163,20 +222,20 @@ match_primary (gfc_expr **result) if (gfc_match_char ('(') != MATCH_YES) return MATCH_NO; - m = gfc_match_expr (&e); - if (m == MATCH_NO) - goto syntax; - if (m == MATCH_ERROR) + m = match_conditional (&e); + if (m != MATCH_YES) return m; m = gfc_match_char (')'); if (m == MATCH_NO) gfc_error ("Expected a right parenthesis in expression at %C"); - /* Now we have the expression inside the parentheses, build the - expression pointing to it. By 7.1.7.2, any expression in - parentheses shall be treated as a data entity. */ - *result = gfc_get_parentheses (e); + /* Now we have the expression inside the parentheses, build the expression + pointing to it. By 7.1.7.2, any expression in parentheses shall be treated + as a data entity. + Note that if the expression is a conditional expression, we will omit the + extra parentheses. */ + *result = e->expr_type == EXPR_CONDITIONAL ? e : gfc_get_parentheses (e); if (m != MATCH_YES) { @@ -185,10 +244,6 @@ match_primary (gfc_expr **result) } return MATCH_YES; - -syntax: - gfc_error (expression_syntax); - return MATCH_ERROR; } diff --git a/gcc/fortran/module.cc b/gcc/fortran/module.cc index e05b08b..3168a60 100644 --- a/gcc/fortran/module.cc +++ b/gcc/fortran/module.cc @@ -3622,7 +3622,9 @@ static const mstring expr_types[] = { minit ("ARRAY", EXPR_ARRAY), minit ("NULL", EXPR_NULL), minit ("COMPCALL", EXPR_COMPCALL), - minit (NULL, -1) + minit ("PPC", EXPR_PPC), + minit ("CONDITIONAL", EXPR_CONDITIONAL), + minit (NULL, -1), }; /* INTRINSIC_ASSIGN is missing because it is used as an index for @@ -3843,6 +3845,12 @@ mio_expr (gfc_expr **ep) break; + case EXPR_CONDITIONAL: + mio_expr (&e->value.conditional.condition); + mio_expr (&e->value.conditional.true_expr); + mio_expr (&e->value.conditional.false_expr); + break; + case EXPR_FUNCTION: mio_symtree_ref (&e->symtree); mio_actual_arglist (&e->value.function.actual, false); diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 1a7c9dd..b83961f 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -4989,6 +4989,73 @@ simplify_op: return t; } +static bool +resolve_conditional (gfc_expr *expr) +{ + gfc_expr *condition, *true_expr, *false_expr; + + condition = expr->value.conditional.condition; + true_expr = expr->value.conditional.true_expr; + false_expr = expr->value.conditional.false_expr; + + if (!gfc_resolve_expr (condition) || !gfc_resolve_expr (true_expr) + || !gfc_resolve_expr (false_expr)) + return false; + + if (condition->ts.type != BT_LOGICAL || condition->rank != 0) + { + gfc_error ( + "Condition in conditional expression must be a scalar logical at %L", + &condition->where); + return false; + } + + if (true_expr->ts.type != false_expr->ts.type) + { + gfc_error ("expr at %L and expr at %L in conditional expression " + "must have the same declared type", + &true_expr->where, &false_expr->where); + return false; + } + + if (true_expr->ts.kind != false_expr->ts.kind) + { + gfc_error ("expr at %L and expr at %L in conditional expression " + "must have the same kind parameter", + &true_expr->where, &false_expr->where); + return false; + } + + if (true_expr->rank != false_expr->rank) + { + gfc_error ("expr at %L and expr at %L in conditional expression " + "must have the same rank", + &true_expr->where, &false_expr->where); + return false; + } + + /* TODO: support more data types for conditional expressions */ + if (true_expr->ts.type != BT_INTEGER && true_expr->ts.type != BT_LOGICAL + && true_expr->ts.type != BT_REAL && true_expr->ts.type != BT_COMPLEX) + { + gfc_error ("Sorry, only integer, logical, real and complex types " + "are currently supported for conditional expressions at %L", + &expr->where); + return false; + } + + if (true_expr->rank > 0) + { + gfc_error ("Sorry, array is currently unsupported for conditional " + "expressions at %L", + &expr->where); + return false; + } + + expr->ts = true_expr->ts; + expr->rank = true_expr->rank; + return true; +} /************** Array resolution subroutines **************/ @@ -8040,6 +8107,10 @@ gfc_resolve_expr (gfc_expr *e) t = resolve_operator (e); break; + case EXPR_CONDITIONAL: + t = resolve_conditional (e); + break; + case EXPR_FUNCTION: case EXPR_VARIABLE: diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 0449c26..7f91684 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -12713,6 +12713,15 @@ gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr) return head2; } +static gfc_ss * +gfc_walk_conditional_expr (gfc_ss *ss, gfc_expr *expr) +{ + gfc_ss *head; + + head = gfc_walk_subexpr (ss, expr->value.conditional.true_expr); + head = gfc_walk_subexpr (head, expr->value.conditional.false_expr); + return head; +} /* Reverse a SS chain. */ @@ -12985,6 +12994,10 @@ gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr) head = gfc_walk_op_expr (ss, expr); return head; + case EXPR_CONDITIONAL: + head = gfc_walk_conditional_expr (ss, expr); + return head; + case EXPR_FUNCTION: head = gfc_walk_function_expr (ss, expr); return head; diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index a9ea29f..e0ae41f1 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -4368,6 +4368,58 @@ gfc_conv_expr_op (gfc_se * se, gfc_expr * expr) gfc_add_block_to_block (&se->post, &lse.post); } +static void +gfc_conv_conditional_expr (gfc_se *se, gfc_expr *expr) +{ + gfc_se cond_se, true_se, false_se; + tree condition, true_val, false_val; + tree type; + + gfc_init_se (&cond_se, se); + gfc_init_se (&true_se, se); + gfc_init_se (&false_se, se); + + gfc_conv_expr (&cond_se, expr->value.conditional.condition); + gfc_add_block_to_block (&se->pre, &cond_se.pre); + condition = gfc_evaluate_now (cond_se.expr, &se->pre); + + true_se.want_pointer = se->want_pointer; + gfc_conv_expr (&true_se, expr->value.conditional.true_expr); + true_val = true_se.expr; + false_se.want_pointer = se->want_pointer; + gfc_conv_expr (&false_se, expr->value.conditional.false_expr); + false_val = false_se.expr; + + if (true_se.pre.head != NULL_TREE || false_se.pre.head != NULL_TREE) + gfc_add_expr_to_block ( + &se->pre, + fold_build3_loc (input_location, COND_EXPR, void_type_node, condition, + true_se.pre.head != NULL_TREE + ? gfc_finish_block (&true_se.pre) + : build_empty_stmt (input_location), + false_se.pre.head != NULL_TREE + ? gfc_finish_block (&false_se.pre) + : build_empty_stmt (input_location))); + + if (true_se.post.head != NULL_TREE || false_se.post.head != NULL_TREE) + gfc_add_expr_to_block ( + &se->post, + fold_build3_loc (input_location, COND_EXPR, void_type_node, condition, + true_se.post.head != NULL_TREE + ? gfc_finish_block (&true_se.post) + : build_empty_stmt (input_location), + false_se.post.head != NULL_TREE + ? gfc_finish_block (&false_se.post) + : build_empty_stmt (input_location))); + + type = gfc_typenode_for_spec (&expr->ts); + if (se->want_pointer) + type = build_pointer_type (type); + + se->expr = fold_build3_loc (input_location, COND_EXPR, type, condition, + true_val, false_val); +} + /* If a string's length is one, we convert it to a single character. */ tree @@ -5317,6 +5369,13 @@ gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping, gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op2); break; + case EXPR_CONDITIONAL: + gfc_apply_interface_mapping_to_expr (mapping, + expr->value.conditional.true_expr); + gfc_apply_interface_mapping_to_expr (mapping, + expr->value.conditional.false_expr); + break; + case EXPR_FUNCTION: for (actual = expr->value.function.actual; actual; actual = actual->next) gfc_apply_interface_mapping_to_expr (mapping, actual->expr); @@ -10464,6 +10523,10 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr) gfc_conv_expr_op (se, expr); break; + case EXPR_CONDITIONAL: + gfc_conv_conditional_expr (se, expr); + break; + case EXPR_FUNCTION: gfc_conv_function_expr (se, expr); break; @@ -10607,6 +10670,13 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr) return; } + if (expr->expr_type == EXPR_CONDITIONAL) + { + se->want_pointer = 1; + gfc_conv_expr (se, expr); + return; + } + if (expr->expr_type == EXPR_FUNCTION && ((expr->value.function.esym && expr->value.function.esym->result diff --git a/gcc/testsuite/gfortran.dg/conditional_1.f90 b/gcc/testsuite/gfortran.dg/conditional_1.f90 new file mode 100644 index 0000000..ca7d21d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_1.f90 @@ -0,0 +1,32 @@ +! { dg-do run } +! { dg-options "-std=f2023" } +program conditional_simple + implicit none + integer :: i = 42 + logical :: l = .true. + real(4) :: r1 = 1.e-4, r2 = 1.e-5 + complex :: z = (3.0, 4.0) + + i = (i > 0 ? 1 : -1) + if (i /= 1) stop 1 + + i = 0 + i = (i > 0 ? 1 : i < 0 ? -1 : 0) + if (i /= 0) stop 2 + + i = 0 + i = (i > 0 ? 1 : (i < 0 ? -1 : 0)) + if (i /= 0) stop 3 + + i = 0 + i = (l .eqv. .false. ? 1 : 0) + if (i /= 0) stop 4 + + i = 0 + i = (r1 /= r2 ? 0 : 1) + if (i /= 0) stop 5 + + i = 0 + z = (i /= 0 ? z : (-3.0, -4.0)) + if (z /= (-3.0, -4.0)) stop 6 +end program conditional_simple diff --git a/gcc/testsuite/gfortran.dg/conditional_2.f90 b/gcc/testsuite/gfortran.dg/conditional_2.f90 new file mode 100644 index 0000000..e78cd08 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_2.f90 @@ -0,0 +1,13 @@ +! { dg-do run } +! { dg-options "-std=f2023" } +program conditional_constant + implicit none + integer :: i = 42 + + i = (.true. ? 1 : -1) + if (i /= 1) stop 1 + + i = 0 + i = (i > 0 ? 1 : .false. ? -1 : 0) + if (i /= 0) stop 2 +end program conditional_constant diff --git a/gcc/testsuite/gfortran.dg/conditional_3.f90 b/gcc/testsuite/gfortran.dg/conditional_3.f90 new file mode 100644 index 0000000..5596cf5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_3.f90 @@ -0,0 +1,9 @@ +! { dg-do compile } +! { dg-options "-std=f2023" } +program conditional_syntax + implicit none + integer :: i = 42 + + i = i > 0 ? 1 : -1 ! { dg-error "Unclassifiable statement at" } + i = (i > 0 ? 1 -1) ! { dg-error "Expected ':' in conditional expression" } +end program conditional_syntax diff --git a/gcc/testsuite/gfortran.dg/conditional_4.f90 b/gcc/testsuite/gfortran.dg/conditional_4.f90 new file mode 100644 index 0000000..38033b9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_4.f90 @@ -0,0 +1,21 @@ +! { dg-do compile } +! { dg-options "-std=f2023" } +program conditional_resolve + implicit none + integer :: i = 42 + integer, parameter :: ucs4 = selected_char_kind('ISO_10646') + character(kind=1) :: k1 = "k1" + character(kind=ucs4) :: k4 = "k4" + integer, dimension(1) :: a_1d + integer, dimension(1, 1) :: a_2d + logical :: l1(2) + integer :: i1(2) + + i = (l1 ? 1 : -1) ! { dg-error "Condition in conditional expression must be a scalar logical" } + i = (i ? 1 : -1) ! { dg-error "Condition in conditional expression must be a scalar logical" } + i = (i /= 0 ? 1 : "oh no") ! { dg-error "must have the same declared type" } + i = (i /= 0 ? k1 : k4) ! { dg-error "must have the same kind parameter" } + i = (i /= 0 ? a_1d : a_2d) ! { dg-error "must have the same rank" } + k1 = (i /= 0 ? k1 : k1) ! { dg-error "Sorry, only integer, logical, real and complex types are currently supported for conditional expressions" } + i1 = (i /= 0 ? i1 : i1 + 1) ! { dg-error "Sorry, array is currently unsupported for conditional expressions" } +end program conditional_resolve diff --git a/gcc/testsuite/gfortran.dg/conditional_5.f90 b/gcc/testsuite/gfortran.dg/conditional_5.f90 new file mode 100644 index 0000000..98b479d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_5.f90 @@ -0,0 +1,7 @@ +! { dg-do compile } +! { dg-options "-std=f2018" } +program conditional_std + implicit none + integer :: i = 42 + i = (i > 0 ? 1 : -1) ! { dg-error "Fortran 2023: Conditional expression at" } +end program conditional_std diff --git a/gcc/testsuite/gfortran.dg/conditional_6.f90 b/gcc/testsuite/gfortran.dg/conditional_6.f90 new file mode 100644 index 0000000..c9ac713 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_6.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-std=f2023" } +program conditional_arg + implicit none + integer :: a = 4 + integer :: b = 5 + call five((a < 5 ? a : b)) + if (a /= 5) stop 1 +contains + subroutine five(x) + integer, optional :: x + if (present(x)) then + x = 5 + end if + end subroutine five +end program conditional_arg diff --git a/gcc/testsuite/gfortran.dg/conditional_7.f90 b/gcc/testsuite/gfortran.dg/conditional_7.f90 new file mode 100644 index 0000000..87e621a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_7.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! { dg-options "-std=f2023" } +module m + contains + function f(n) result(str) + integer, value :: n + character(len=(n > 5 ? n : 5)) :: str + str = "" + str(1:5) = "abcde" + end +end diff --git a/gcc/testsuite/gfortran.dg/conditional_8.f90 b/gcc/testsuite/gfortran.dg/conditional_8.f90 new file mode 100644 index 0000000..913acc7f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_8.f90 @@ -0,0 +1,14 @@ +! { dg-do run } +! { dg-options "-std=f2023" } +implicit none +integer :: aa(2) +aa = [1, 2] + +print *, (aa(1) > 0 ? aa(2) : g()) +contains +integer function g() + allocatable :: g + error stop "should not be called" + g = 3 +end +end diff --git a/gcc/testsuite/gfortran.dg/conditional_9.f90 b/gcc/testsuite/gfortran.dg/conditional_9.f90 new file mode 100644 index 0000000..d1bb15e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/conditional_9.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! { dg-options "-std=f2023" } +implicit none +integer :: i, j +do concurrent (i=(j > 1 ? 0 : 1) : 5) local(j) ! { dg-error "must not appear in LOCAL locality-spec at" } +end do +do concurrent (i=(.true. ? j : 1) : 5) local(j) ! { dg-error "must not appear in LOCAL locality-spec at" } +end do +do concurrent (i=(.false. ? 1 : j) : 5) local(j) ! { dg-error "must not appear in LOCAL locality-spec at" } +end do +end |