get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2226758/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2226758,
    "url": "http://patchwork.ozlabs.org/api/patches/2226758/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.1@forge-stage.sourceware.org/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.1@forge-stage.sourceware.org>",
    "list_archive_url": null,
    "date": "2026-04-22T18:46:59",
    "name": "[v1,1/1] fortran: implement conditional expression for fortran 2023",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d62384349fbc2d4d9dd483ca3c70e42d5dabc0bf",
    "submitter": {
        "id": 93230,
        "url": "http://patchwork.ozlabs.org/api/people/93230/?format=api",
        "name": "yuao via Sourceware Forge",
        "email": "forge-bot+yuao@forge-stage.sourceware.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.1@forge-stage.sourceware.org/mbox/",
    "series": [
        {
            "id": 501093,
            "url": "http://patchwork.ozlabs.org/api/series/501093/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=501093",
            "date": "2026-04-22T18:46:59",
            "name": "fortran: implement conditional expression for fortran 2023",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/501093/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2226758/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2226758/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org",
            "sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g18Ls2dw2z1yD5\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 05:25:09 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8574141627F9\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 19:25:07 +0000 (GMT)",
            "from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 44D684716838\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:48:23 +0000 (GMT)",
            "from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id 213DC43545\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:48:23 +0000 (UTC)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 8574141627F9",
            "OpenDKIM Filter v2.11.0 sourceware.org 44D684716838"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 44D684716838",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 44D684716838",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776883703; cv=none;\n b=uJJeAbV23QnbNROSv4EO5nqubjBohkp4DgPJdYAtKoH9o3hdjqRh+3jZSJXRM1pOukXzLPGoXNt3ieqGfHrG7jaoWCGzXrWRanGvvpeDtVz2DcaeRMD7n9Tj4M5dIPTJShxM9UG001XTy+xTf+FUyA7IDnZUuowwyisjCcCnbFI=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776883703; c=relaxed/simple;\n bh=vOyW/gYU/TWoP7N1RZBBDQZpTala7Ltf0wfMszdSrak=;\n h=From:Date:Subject:To:Message-ID;\n b=SMxn2M0NJmT5FTE8ux16C9UtBUgEYEZrwbWsYGu1jVcfF5+Ut+VUpmnoNpPayVnDSUpdviYBzif7y/CoU4Gg2jThnrW9uhA7jbHG1o8urQxKhsk3S+TbCr75pDrfPcmnNQ4dy82q2WXge9lVZYgHeFT2LxX8W8XNadwZ7dSicuk=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "From": "yuao via Sourceware Forge <forge-bot+yuao@forge-stage.sourceware.org>",
        "Date": "Wed, 22 Apr 2026 18:46:59 +0000",
        "Subject": "[PATCH v1 1/1] fortran: implement conditional expression for fortran\n 2023",
        "To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>",
        "Message-ID": "\n <bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.1@forge-stage.sourceware.org>",
        "X-Mailer": "batrachomyomachia",
        "X-Pull-Request-Organization": "gcc",
        "X-Pull-Request-Repository": "gcc-TEST",
        "X-Pull-Request": "https://forge.sourceware.org/gcc/gcc-TEST/pulls/80",
        "References": "\n <bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.0@forge-stage.sourceware.org>",
        "In-Reply-To": "\n <bmm.hhup2dpico.gcc.gcc-TEST.yuao.80.1.0@forge-stage.sourceware.org>",
        "X-Patch-URL": "\n https://forge.sourceware.org/yuao/gcc-TEST/commit/12edebd03a6e418f14688eb7bb4a04a4bb7266e1",
        "X-BeenThere": "gcc-patches@gcc.gnu.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>",
        "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>",
        "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>",
        "Reply-To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>,\n yuao@noreply.localhost",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "From: Yuao Ma <c8ef@outlook.com>\n\nThis patch adds support for conditional expressions in Fortran 2023 for a\nlimited set of types (logical, numerical), and also includes limited support\nfor conditional arguments without `.nil.` support.\n\ngcc/fortran/ChangeLog:\n\n\t* dump-parse-tree.cc (show_expr): Add support for EXPR_CONDITIONAL.\n\t* expr.cc (gfc_get_conditional_expr): Add cond-expr constructor.\n\t(gfc_copy_expr, free_expr0, gfc_is_constant_expr,\n\tsimplify_conditional, gfc_simplify_expr, gfc_check_init_expr,\n\tcheck_restricted, gfc_traverse_expr): Add support for EXPR_CONDITIONAL.\n\t* frontend-passes.cc (gfc_expr_walker): Ditto.\n\t* gfortran.h (enum expr_t): Add EXPR_CONDITIONAL.\n\t(gfc_get_operator_expr): Format fix.\n\t(gfc_get_conditional_expr): New decl.\n\t* matchexp.cc\n\t(match_conditional, match_primary): Parsing for EXPR_CONDITIONAL.\n\t* module.cc (mio_expr): Add support for EXPR_CONDITIONAL.\n\t* resolve.cc (resolve_conditional, gfc_resolve_expr): Ditto.\n\t* trans-array.cc (gfc_walk_conditional_expr, gfc_walk_subexpr): Ditto.\n\t* trans-expr.cc\n\t(gfc_conv_conditional_expr): Codegen for EXPR_CONDITIONAL.\n\t(gfc_apply_interface_mapping_to_expr, gfc_conv_expr,\n\tgfc_conv_expr_reference): Add support for EXPR_CONDITIONAL.\n\ngcc/testsuite/ChangeLog:\n\n\t* gfortran.dg/conditional_1.f90: New test.\n\t* gfortran.dg/conditional_2.f90: New test.\n\t* gfortran.dg/conditional_3.f90: New test.\n\t* gfortran.dg/conditional_4.f90: New test.\n\t* gfortran.dg/conditional_5.f90: New test.\n\t* gfortran.dg/conditional_6.f90: New test.\n\t* gfortran.dg/conditional_7.f90: New test.\n\t* gfortran.dg/conditional_8.f90: New test.\n\t* gfortran.dg/conditional_9.f90: New test.\n---\n gcc/fortran/dump-parse-tree.cc              |  10 ++\n gcc/fortran/expr.cc                         | 118 ++++++++++++++++++++\n gcc/fortran/frontend-passes.cc              |   5 +\n gcc/fortran/gfortran.h                      |  30 ++++-\n gcc/fortran/matchexp.cc                     |  79 +++++++++++--\n gcc/fortran/module.cc                       |  10 +-\n gcc/fortran/resolve.cc                      |  71 ++++++++++++\n gcc/fortran/trans-array.cc                  |  13 +++\n gcc/fortran/trans-expr.cc                   |  70 ++++++++++++\n gcc/testsuite/gfortran.dg/conditional_1.f90 |  32 ++++++\n gcc/testsuite/gfortran.dg/conditional_2.f90 |  13 +++\n gcc/testsuite/gfortran.dg/conditional_3.f90 |   9 ++\n gcc/testsuite/gfortran.dg/conditional_4.f90 |  21 ++++\n gcc/testsuite/gfortran.dg/conditional_5.f90 |   7 ++\n gcc/testsuite/gfortran.dg/conditional_6.f90 |  16 +++\n gcc/testsuite/gfortran.dg/conditional_7.f90 |  11 ++\n gcc/testsuite/gfortran.dg/conditional_8.f90 |  14 +++\n gcc/testsuite/gfortran.dg/conditional_9.f90 |  11 ++\n 18 files changed, 522 insertions(+), 18 deletions(-)\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_1.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_2.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_3.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_4.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_5.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_6.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_7.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_8.f90\n create mode 100644 gcc/testsuite/gfortran.dg/conditional_9.f90",
    "diff": "diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc\nindex 3cd2eeef11a6..eda0659d6e23 100644\n--- a/gcc/fortran/dump-parse-tree.cc\n+++ b/gcc/fortran/dump-parse-tree.cc\n@@ -767,6 +767,16 @@ show_expr (gfc_expr *p)\n \n       break;\n \n+    case EXPR_CONDITIONAL:\n+      fputc ('(', dumpfile);\n+      show_expr (p->value.conditional.condition);\n+      fputs (\" ? \", dumpfile);\n+      show_expr (p->value.conditional.true_expr);\n+      fputs (\" : \", dumpfile);\n+      show_expr (p->value.conditional.false_expr);\n+      fputc (')', dumpfile);\n+      break;\n+\n     case EXPR_COMPCALL:\n       show_compcall (p);\n       break;\ndiff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc\nindex 3dbf8cb287aa..a11ff79ab6be 100644\n--- a/gcc/fortran/expr.cc\n+++ b/gcc/fortran/expr.cc\n@@ -116,6 +116,25 @@ gfc_get_operator_expr (locus *where, gfc_intrinsic_op op,\n   return e;\n }\n \n+/* Get a new expression node that is an conditional expression node.  */\n+\n+gfc_expr *\n+gfc_get_conditional_expr (locus *where, gfc_expr *condition,\n+\t\t\t  gfc_expr *true_expr, gfc_expr *false_expr)\n+{\n+  gfc_expr *e;\n+\n+  e = gfc_get_expr ();\n+  e->expr_type = EXPR_CONDITIONAL;\n+  e->value.conditional.condition = condition;\n+  e->value.conditional.true_expr = true_expr;\n+  e->value.conditional.false_expr = false_expr;\n+\n+  if (where)\n+    e->where = *where;\n+\n+  return e;\n+}\n \n /* Get a new expression node that is an structure constructor\n    of given type and kind.  */\n@@ -393,6 +412,15 @@ gfc_copy_expr (gfc_expr *p)\n \n       break;\n \n+    case EXPR_CONDITIONAL:\n+      q->value.conditional.condition\n+\t= gfc_copy_expr (p->value.conditional.condition);\n+      q->value.conditional.true_expr\n+\t= gfc_copy_expr (p->value.conditional.true_expr);\n+      q->value.conditional.false_expr\n+\t= gfc_copy_expr (p->value.conditional.false_expr);\n+      break;\n+\n     case EXPR_FUNCTION:\n       q->value.function.actual =\n \tgfc_copy_actual_arglist (p->value.function.actual);\n@@ -502,6 +530,12 @@ free_expr0 (gfc_expr *e)\n \tgfc_free_expr (e->value.op.op2);\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      gfc_free_expr (e->value.conditional.condition);\n+      gfc_free_expr (e->value.conditional.true_expr);\n+      gfc_free_expr (e->value.conditional.false_expr);\n+      break;\n+\n     case EXPR_FUNCTION:\n       gfc_free_actual_arglist (e->value.function.actual);\n       break;\n@@ -1083,6 +1117,11 @@ gfc_is_constant_expr (gfc_expr *e)\n \t      && (e->value.op.op2 == NULL\n \t\t  || gfc_is_constant_expr (e->value.op.op2)));\n \n+    case EXPR_CONDITIONAL:\n+      return gfc_is_constant_expr (e->value.conditional.condition)\n+\t     && gfc_is_constant_expr (e->value.conditional.true_expr)\n+\t     && gfc_is_constant_expr (e->value.conditional.false_expr);\n+\n     case EXPR_VARIABLE:\n       /* The only context in which this can occur is in a parameterized\n \t derived type declaration, so returning true is OK.  */\n@@ -1354,6 +1393,43 @@ simplify_intrinsic_op (gfc_expr *p, int type)\n   return true;\n }\n \n+/* Try to collapse conditional expressions.  */\n+\n+static bool\n+simplify_conditional (gfc_expr *p, int type)\n+{\n+  gfc_expr *condition, *true_expr, *false_expr;\n+\n+  condition = p->value.conditional.condition;\n+  true_expr = p->value.conditional.true_expr;\n+  false_expr = p->value.conditional.false_expr;\n+\n+  if (!gfc_simplify_expr (condition, type)\n+      || !gfc_simplify_expr (true_expr, type)\n+      || !gfc_simplify_expr (false_expr, type))\n+    return false;\n+\n+  if (!gfc_is_constant_expr (condition))\n+    return true;\n+\n+  p->value.conditional.condition = NULL;\n+  p->value.conditional.true_expr = NULL;\n+  p->value.conditional.false_expr = NULL;\n+\n+  if (condition->value.logical)\n+    {\n+      gfc_replace_expr (p, true_expr);\n+      gfc_free_expr (false_expr);\n+    }\n+  else\n+    {\n+      gfc_replace_expr (p, false_expr);\n+      gfc_free_expr (true_expr);\n+    }\n+  gfc_free_expr (condition);\n+\n+  return true;\n+}\n \n /* Subroutine to simplify constructor expressions.  Mutually recursive\n    with gfc_simplify_expr().  */\n@@ -2459,6 +2535,11 @@ gfc_simplify_expr (gfc_expr *p, int type)\n \treturn false;\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      if (!simplify_conditional (p, type))\n+\treturn false;\n+      break;\n+\n     case EXPR_VARIABLE:\n       /* Only substitute array parameter variables if we are in an\n \t initialization expression, or we want a subsection.  */\n@@ -3133,6 +3214,20 @@ gfc_check_init_expr (gfc_expr *e)\n \n       break;\n \n+    case EXPR_CONDITIONAL:\n+      t = gfc_check_init_expr (e->value.conditional.condition);\n+      if (!t)\n+\tbreak;\n+      t = gfc_check_init_expr (e->value.conditional.true_expr);\n+      if (!t)\n+\tbreak;\n+      t = gfc_check_init_expr (e->value.conditional.false_expr);\n+      if (t)\n+\tt = gfc_simplify_expr (e, 0);\n+      else\n+\tt = false;\n+      break;\n+\n     case EXPR_FUNCTION:\n       t = false;\n \n@@ -3609,6 +3704,20 @@ check_restricted (gfc_expr *e)\n \n       break;\n \n+    case EXPR_CONDITIONAL:\n+      t = check_restricted (e->value.conditional.condition);\n+      if (!t)\n+\tbreak;\n+      t = check_restricted (e->value.conditional.true_expr);\n+      if (!t)\n+\tbreak;\n+      t = check_restricted (e->value.conditional.false_expr);\n+      if (t)\n+\tt = gfc_simplify_expr (e, 0);\n+      else\n+\tt = false;\n+      break;\n+\n     case EXPR_FUNCTION:\n       if (e->value.function.esym)\n \t{\n@@ -5700,6 +5809,15 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym,\n \treturn true;\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      if (gfc_traverse_expr (expr->value.conditional.condition, sym, func, f))\n+\treturn true;\n+      if (gfc_traverse_expr (expr->value.conditional.true_expr, sym, func, f))\n+\treturn true;\n+      if (gfc_traverse_expr (expr->value.conditional.false_expr, sym, func, f))\n+\treturn true;\n+      break;\n+\n     default:\n       gcc_unreachable ();\n       break;\ndiff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc\nindex 02a0a2326a66..4a468b936004 100644\n--- a/gcc/fortran/frontend-passes.cc\n+++ b/gcc/fortran/frontend-passes.cc\n@@ -5218,6 +5218,11 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)\n \t    for (a = (*e)->value.function.actual; a; a = a->next)\n \t      WALK_SUBEXPR (a->expr);\n \t    break;\n+\t  case EXPR_CONDITIONAL:\n+\t    WALK_SUBEXPR ((*e)->value.conditional.condition);\n+\t    WALK_SUBEXPR ((*e)->value.conditional.true_expr);\n+\t    WALK_SUBEXPR ((*e)->value.conditional.false_expr);\n+\t    break;\n \t  case EXPR_COMPCALL:\n \t  case EXPR_PPC:\n \t    WALK_SUBEXPR ((*e)->value.compcall.base_object);\ndiff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h\nindex 482031d26005..2e6b368b4c26 100644\n--- a/gcc/fortran/gfortran.h\n+++ b/gcc/fortran/gfortran.h\n@@ -176,8 +176,19 @@ enum gfc_source_form\n \n /* Expression node types.  */\n enum expr_t\n-  { EXPR_UNKNOWN = 0, EXPR_OP = 1, EXPR_FUNCTION, EXPR_CONSTANT, EXPR_VARIABLE,\n-  EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL, EXPR_COMPCALL, EXPR_PPC\n+{\n+  EXPR_UNKNOWN = 0,\n+  EXPR_OP = 1,\n+  EXPR_FUNCTION,\n+  EXPR_CONSTANT,\n+  EXPR_VARIABLE,\n+  EXPR_SUBSTRING,\n+  EXPR_STRUCTURE,\n+  EXPR_ARRAY,\n+  EXPR_NULL,\n+  EXPR_COMPCALL,\n+  EXPR_PPC,\n+  EXPR_CONDITIONAL,\n };\n \n /* Array types.  */\n@@ -2809,8 +2820,14 @@ typedef struct gfc_expr\n     character;\n \n     gfc_constructor_base constructor;\n-  }\n-  value;\n+\n+    struct\n+    {\n+      struct gfc_expr *condition;\n+      struct gfc_expr *true_expr;\n+      struct gfc_expr *false_expr;\n+    } conditional;\n+  } value;\n \n   /* Used to store PDT expression lists associated with expressions.  */\n   gfc_actual_arglist *param_list;\n@@ -3925,7 +3942,10 @@ bool gfc_is_ptr_fcn (gfc_expr *);\n gfc_expr *gfc_get_expr (void);\n gfc_expr *gfc_get_array_expr (bt type, int kind, locus *);\n gfc_expr *gfc_get_null_expr (locus *);\n-gfc_expr *gfc_get_operator_expr (locus *, gfc_intrinsic_op,gfc_expr *, gfc_expr *);\n+gfc_expr *gfc_get_operator_expr (locus *, gfc_intrinsic_op, gfc_expr *,\n+\t\t\t\t gfc_expr *);\n+gfc_expr *gfc_get_conditional_expr (locus *, gfc_expr *, gfc_expr *,\n+\t\t\t\t    gfc_expr *);\n gfc_expr *gfc_get_structure_constructor_expr (bt, int, locus *);\n gfc_expr *gfc_get_constant_expr (bt, int, locus *);\n gfc_expr *gfc_get_character_expr (int, locus *, const char *, gfc_charlen_t len);\ndiff --git a/gcc/fortran/matchexp.cc b/gcc/fortran/matchexp.cc\nindex 9b66243b4fa1..e3a992538413 100644\n--- a/gcc/fortran/matchexp.cc\n+++ b/gcc/fortran/matchexp.cc\n@@ -138,6 +138,65 @@ gfc_get_parentheses (gfc_expr *e)\n   return e2;\n }\n \n+/* Match a conditional expression.  */\n+\n+static match\n+match_conditional (gfc_expr **result)\n+{\n+  gfc_expr *condition, *true_expr, *false_expr;\n+  locus where;\n+  match m;\n+\n+  where = gfc_current_locus;\n+\n+  m = gfc_match_expr (&condition);\n+  if (m != MATCH_YES)\n+    {\n+      gfc_error (expression_syntax);\n+      return MATCH_ERROR;\n+    }\n+\n+  m = gfc_match_char ('?');\n+  if (m != MATCH_YES)\n+    {\n+      *result = condition;\n+      return MATCH_YES;\n+    }\n+  else if (!gfc_notify_std (GFC_STD_F2023, \"Conditional expression at %L\",\n+\t\t\t    &where))\n+    {\n+      gfc_free_expr (condition);\n+      return MATCH_ERROR;\n+    }\n+\n+  gfc_gobble_whitespace ();\n+  m = gfc_match_expr (&true_expr);\n+  if (m != MATCH_YES)\n+    {\n+      gfc_free_expr (condition);\n+      return m;\n+    }\n+\n+  m = gfc_match_char (':');\n+  if (m != MATCH_YES)\n+    {\n+      gfc_error (\"Expected ':' in conditional expression at %C\");\n+      gfc_free_expr (condition);\n+      gfc_free_expr (true_expr);\n+      return MATCH_ERROR;\n+    }\n+\n+  m = match_conditional (&false_expr);\n+  if (m != MATCH_YES)\n+    {\n+      gfc_free_expr (condition);\n+      gfc_free_expr (true_expr);\n+      return m;\n+    }\n+\n+  *result = gfc_get_conditional_expr (&where, condition, true_expr, false_expr);\n+  return MATCH_YES;\n+}\n \n /* Match a primary expression.  */\n \n@@ -163,20 +222,20 @@ match_primary (gfc_expr **result)\n   if (gfc_match_char ('(') != MATCH_YES)\n     return MATCH_NO;\n \n-  m = gfc_match_expr (&e);\n-  if (m == MATCH_NO)\n-    goto syntax;\n-  if (m == MATCH_ERROR)\n+  m = match_conditional (&e);\n+  if (m != MATCH_YES)\n     return m;\n \n   m = gfc_match_char (')');\n   if (m == MATCH_NO)\n     gfc_error (\"Expected a right parenthesis in expression at %C\");\n \n-  /* Now we have the expression inside the parentheses, build the\n-     expression pointing to it. By 7.1.7.2, any expression in\n-     parentheses shall be treated as a data entity.  */\n-  *result = gfc_get_parentheses (e);\n+  /* Now we have the expression inside the parentheses, build the expression\n+     pointing to it. By 7.1.7.2, any expression in parentheses shall be treated\n+     as a data entity.\n+     Note that if the expression is a conditional expression, we will omit the\n+     extra parentheses.  */\n+  *result = e->expr_type == EXPR_CONDITIONAL ? e : gfc_get_parentheses (e);\n \n   if (m != MATCH_YES)\n     {\n@@ -185,10 +244,6 @@ match_primary (gfc_expr **result)\n     }\n \n   return MATCH_YES;\n-\n-syntax:\n-  gfc_error (expression_syntax);\n-  return MATCH_ERROR;\n }\n \n \ndiff --git a/gcc/fortran/module.cc b/gcc/fortran/module.cc\nindex e05b08bd14ed..3168a6082eb6 100644\n--- a/gcc/fortran/module.cc\n+++ b/gcc/fortran/module.cc\n@@ -3622,7 +3622,9 @@ static const mstring expr_types[] = {\n     minit (\"ARRAY\", EXPR_ARRAY),\n     minit (\"NULL\", EXPR_NULL),\n     minit (\"COMPCALL\", EXPR_COMPCALL),\n-    minit (NULL, -1)\n+    minit (\"PPC\", EXPR_PPC),\n+    minit (\"CONDITIONAL\", EXPR_CONDITIONAL),\n+    minit (NULL, -1),\n };\n \n /* INTRINSIC_ASSIGN is missing because it is used as an index for\n@@ -3843,6 +3845,12 @@ mio_expr (gfc_expr **ep)\n \n       break;\n \n+    case EXPR_CONDITIONAL:\n+      mio_expr (&e->value.conditional.condition);\n+      mio_expr (&e->value.conditional.true_expr);\n+      mio_expr (&e->value.conditional.false_expr);\n+      break;\n+\n     case EXPR_FUNCTION:\n       mio_symtree_ref (&e->symtree);\n       mio_actual_arglist (&e->value.function.actual, false);\ndiff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc\nindex 1a7c9dddb15b..b83961fe6f10 100644\n--- a/gcc/fortran/resolve.cc\n+++ b/gcc/fortran/resolve.cc\n@@ -4989,6 +4989,73 @@ simplify_op:\n   return t;\n }\n \n+static bool\n+resolve_conditional (gfc_expr *expr)\n+{\n+  gfc_expr *condition, *true_expr, *false_expr;\n+\n+  condition = expr->value.conditional.condition;\n+  true_expr = expr->value.conditional.true_expr;\n+  false_expr = expr->value.conditional.false_expr;\n+\n+  if (!gfc_resolve_expr (condition) || !gfc_resolve_expr (true_expr)\n+      || !gfc_resolve_expr (false_expr))\n+    return false;\n+\n+  if (condition->ts.type != BT_LOGICAL || condition->rank != 0)\n+    {\n+      gfc_error (\n+\t\"Condition in conditional expression must be a scalar logical at %L\",\n+\t&condition->where);\n+      return false;\n+    }\n+\n+  if (true_expr->ts.type != false_expr->ts.type)\n+    {\n+      gfc_error (\"expr at %L and expr at %L in conditional expression \"\n+\t\t \"must have the same declared type\",\n+\t\t &true_expr->where, &false_expr->where);\n+      return false;\n+    }\n+\n+  if (true_expr->ts.kind != false_expr->ts.kind)\n+    {\n+      gfc_error (\"expr at %L and expr at %L in conditional expression \"\n+\t\t \"must have the same kind parameter\",\n+\t\t &true_expr->where, &false_expr->where);\n+      return false;\n+    }\n+\n+  if (true_expr->rank != false_expr->rank)\n+    {\n+      gfc_error (\"expr at %L and expr at %L in conditional expression \"\n+\t\t \"must have the same rank\",\n+\t\t &true_expr->where, &false_expr->where);\n+      return false;\n+    }\n+\n+  /* TODO: support more data types for conditional expressions  */\n+  if (true_expr->ts.type != BT_INTEGER && true_expr->ts.type != BT_LOGICAL\n+      && true_expr->ts.type != BT_REAL && true_expr->ts.type != BT_COMPLEX)\n+    {\n+      gfc_error (\"Sorry, only integer, logical, real and complex types \"\n+\t\t \"are currently supported for conditional expressions at %L\",\n+\t\t &expr->where);\n+      return false;\n+    }\n+\n+  if (true_expr->rank > 0)\n+    {\n+      gfc_error (\"Sorry, array is currently unsupported for conditional \"\n+\t\t \"expressions at %L\",\n+\t\t &expr->where);\n+      return false;\n+    }\n+\n+  expr->ts = true_expr->ts;\n+  expr->rank = true_expr->rank;\n+  return true;\n+}\n \n /************** Array resolution subroutines **************/\n \n@@ -8040,6 +8107,10 @@ gfc_resolve_expr (gfc_expr *e)\n       t = resolve_operator (e);\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      t = resolve_conditional (e);\n+      break;\n+\n     case EXPR_FUNCTION:\n     case EXPR_VARIABLE:\n \ndiff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc\nindex 0449c26ce6d5..7f9168410a2e 100644\n--- a/gcc/fortran/trans-array.cc\n+++ b/gcc/fortran/trans-array.cc\n@@ -12713,6 +12713,15 @@ gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)\n   return head2;\n }\n \n+static gfc_ss *\n+gfc_walk_conditional_expr (gfc_ss *ss, gfc_expr *expr)\n+{\n+  gfc_ss *head;\n+\n+  head = gfc_walk_subexpr (ss, expr->value.conditional.true_expr);\n+  head = gfc_walk_subexpr (head, expr->value.conditional.false_expr);\n+  return head;\n+}\n \n /* Reverse a SS chain.  */\n \n@@ -12985,6 +12994,10 @@ gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)\n       head = gfc_walk_op_expr (ss, expr);\n       return head;\n \n+    case EXPR_CONDITIONAL:\n+      head = gfc_walk_conditional_expr (ss, expr);\n+      return head;\n+\n     case EXPR_FUNCTION:\n       head = gfc_walk_function_expr (ss, expr);\n       return head;\ndiff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc\nindex a9ea29f760fe..e0ae41f12c6d 100644\n--- a/gcc/fortran/trans-expr.cc\n+++ b/gcc/fortran/trans-expr.cc\n@@ -4368,6 +4368,58 @@ gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)\n   gfc_add_block_to_block (&se->post, &lse.post);\n }\n \n+static void\n+gfc_conv_conditional_expr (gfc_se *se, gfc_expr *expr)\n+{\n+  gfc_se cond_se, true_se, false_se;\n+  tree condition, true_val, false_val;\n+  tree type;\n+\n+  gfc_init_se (&cond_se, se);\n+  gfc_init_se (&true_se, se);\n+  gfc_init_se (&false_se, se);\n+\n+  gfc_conv_expr (&cond_se, expr->value.conditional.condition);\n+  gfc_add_block_to_block (&se->pre, &cond_se.pre);\n+  condition = gfc_evaluate_now (cond_se.expr, &se->pre);\n+\n+  true_se.want_pointer = se->want_pointer;\n+  gfc_conv_expr (&true_se, expr->value.conditional.true_expr);\n+  true_val = true_se.expr;\n+  false_se.want_pointer = se->want_pointer;\n+  gfc_conv_expr (&false_se, expr->value.conditional.false_expr);\n+  false_val = false_se.expr;\n+\n+  if (true_se.pre.head != NULL_TREE || false_se.pre.head != NULL_TREE)\n+    gfc_add_expr_to_block (\n+      &se->pre,\n+      fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,\n+\t\t       true_se.pre.head != NULL_TREE\n+\t\t\t ? gfc_finish_block (&true_se.pre)\n+\t\t\t : build_empty_stmt (input_location),\n+\t\t       false_se.pre.head != NULL_TREE\n+\t\t\t ? gfc_finish_block (&false_se.pre)\n+\t\t\t : build_empty_stmt (input_location)));\n+\n+  if (true_se.post.head != NULL_TREE || false_se.post.head != NULL_TREE)\n+    gfc_add_expr_to_block (\n+      &se->post,\n+      fold_build3_loc (input_location, COND_EXPR, void_type_node, condition,\n+\t\t       true_se.post.head != NULL_TREE\n+\t\t\t ? gfc_finish_block (&true_se.post)\n+\t\t\t : build_empty_stmt (input_location),\n+\t\t       false_se.post.head != NULL_TREE\n+\t\t\t ? gfc_finish_block (&false_se.post)\n+\t\t\t : build_empty_stmt (input_location)));\n+\n+  type = gfc_typenode_for_spec (&expr->ts);\n+  if (se->want_pointer)\n+    type = build_pointer_type (type);\n+\n+  se->expr = fold_build3_loc (input_location, COND_EXPR, type, condition,\n+\t\t\t      true_val, false_val);\n+}\n+\n /* If a string's length is one, we convert it to a single character.  */\n \n tree\n@@ -5317,6 +5369,13 @@ gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping,\n       gfc_apply_interface_mapping_to_expr (mapping, expr->value.op.op2);\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      gfc_apply_interface_mapping_to_expr (mapping,\n+\t\t\t\t\t   expr->value.conditional.true_expr);\n+      gfc_apply_interface_mapping_to_expr (mapping,\n+\t\t\t\t\t   expr->value.conditional.false_expr);\n+      break;\n+\n     case EXPR_FUNCTION:\n       for (actual = expr->value.function.actual; actual; actual = actual->next)\n \tgfc_apply_interface_mapping_to_expr (mapping, actual->expr);\n@@ -10464,6 +10523,10 @@ gfc_conv_expr (gfc_se * se, gfc_expr * expr)\n       gfc_conv_expr_op (se, expr);\n       break;\n \n+    case EXPR_CONDITIONAL:\n+      gfc_conv_conditional_expr (se, expr);\n+      break;\n+\n     case EXPR_FUNCTION:\n       gfc_conv_function_expr (se, expr);\n       break;\n@@ -10607,6 +10670,13 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)\n       return;\n     }\n \n+  if (expr->expr_type == EXPR_CONDITIONAL)\n+    {\n+      se->want_pointer = 1;\n+      gfc_conv_expr (se, expr);\n+      return;\n+    }\n+\n   if (expr->expr_type == EXPR_FUNCTION\n       && ((expr->value.function.esym\n \t   && expr->value.function.esym->result\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_1.f90 b/gcc/testsuite/gfortran.dg/conditional_1.f90\nnew file mode 100644\nindex 000000000000..ca7d21db1a7d\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_1.f90\n@@ -0,0 +1,32 @@\n+! { dg-do run }\n+! { dg-options \"-std=f2023\" }\n+program conditional_simple\n+  implicit none\n+  integer :: i = 42\n+  logical :: l = .true.\n+  real(4) :: r1 = 1.e-4, r2 = 1.e-5\n+  complex :: z = (3.0, 4.0)\n+\n+  i = (i > 0 ? 1 : -1)\n+  if (i /= 1) stop 1\n+\n+  i = 0\n+  i = (i > 0 ? 1 : i < 0 ? -1 : 0)\n+  if (i /= 0) stop 2\n+\n+  i = 0\n+  i = (i > 0 ? 1 : (i < 0 ? -1 : 0))\n+  if (i /= 0) stop 3\n+\n+  i = 0\n+  i = (l .eqv. .false. ? 1 : 0)\n+  if (i /= 0) stop 4\n+\n+  i = 0\n+  i = (r1 /= r2 ? 0 : 1)\n+  if (i /= 0) stop 5\n+\n+  i = 0\n+  z = (i /= 0 ? z : (-3.0, -4.0))\n+  if (z /= (-3.0, -4.0)) stop 6\n+end program conditional_simple\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_2.f90 b/gcc/testsuite/gfortran.dg/conditional_2.f90\nnew file mode 100644\nindex 000000000000..e78cd0841543\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_2.f90\n@@ -0,0 +1,13 @@\n+! { dg-do run }\n+! { dg-options \"-std=f2023\" }\n+program conditional_constant\n+  implicit none\n+  integer :: i = 42\n+\n+  i = (.true. ? 1 : -1)\n+  if (i /= 1) stop 1\n+\n+  i = 0\n+  i = (i > 0 ? 1 : .false. ? -1 : 0)\n+  if (i /= 0) stop 2\n+end program conditional_constant\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_3.f90 b/gcc/testsuite/gfortran.dg/conditional_3.f90\nnew file mode 100644\nindex 000000000000..5596cf5a59c5\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_3.f90\n@@ -0,0 +1,9 @@\n+! { dg-do compile }\n+! { dg-options \"-std=f2023\" }\n+program conditional_syntax\n+  implicit none\n+  integer :: i = 42\n+\n+  i = i > 0 ? 1 : -1 ! { dg-error \"Unclassifiable statement at\" }\n+  i = (i > 0 ? 1 -1) ! { dg-error \"Expected ':' in conditional expression\" }\n+end program conditional_syntax\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_4.f90 b/gcc/testsuite/gfortran.dg/conditional_4.f90\nnew file mode 100644\nindex 000000000000..38033b9ec1de\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_4.f90\n@@ -0,0 +1,21 @@\n+! { dg-do compile }\n+! { dg-options \"-std=f2023\" }\n+program conditional_resolve\n+  implicit none\n+  integer :: i = 42\n+  integer, parameter :: ucs4 = selected_char_kind('ISO_10646')\n+  character(kind=1) :: k1 = \"k1\"\n+  character(kind=ucs4) :: k4 = \"k4\"\n+  integer, dimension(1) :: a_1d\n+  integer, dimension(1, 1) :: a_2d\n+  logical :: l1(2)\n+  integer :: i1(2)\n+\n+  i = (l1 ? 1 : -1) ! { dg-error \"Condition in conditional expression must be a scalar logical\" }\n+  i = (i ? 1 : -1) ! { dg-error \"Condition in conditional expression must be a scalar logical\" }\n+  i = (i /= 0 ? 1 : \"oh no\") ! { dg-error \"must have the same declared type\" }\n+  i = (i /= 0 ? k1 : k4) ! { dg-error \"must have the same kind parameter\" }\n+  i = (i /= 0 ? a_1d : a_2d) ! { dg-error \"must have the same rank\" }\n+  k1 = (i /= 0 ? k1 : k1) ! { dg-error \"Sorry, only integer, logical, real and complex types are currently supported for conditional expressions\" }\n+  i1 = (i /= 0 ? i1 : i1 + 1) ! { dg-error \"Sorry, array is currently unsupported for conditional expressions\" }\n+end program conditional_resolve\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_5.f90 b/gcc/testsuite/gfortran.dg/conditional_5.f90\nnew file mode 100644\nindex 000000000000..98b479d3e9df\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_5.f90\n@@ -0,0 +1,7 @@\n+! { dg-do compile }\n+! { dg-options \"-std=f2018\" }\n+program conditional_std\n+  implicit none\n+  integer :: i = 42\n+  i = (i > 0 ? 1 : -1) ! { dg-error \"Fortran 2023: Conditional expression at\" }\n+end program conditional_std\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_6.f90 b/gcc/testsuite/gfortran.dg/conditional_6.f90\nnew file mode 100644\nindex 000000000000..c9ac7132c45f\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_6.f90\n@@ -0,0 +1,16 @@\n+! { dg-do run }\n+! { dg-options \"-std=f2023\" }\n+program conditional_arg\n+  implicit none\n+  integer :: a = 4\n+  integer :: b = 5\n+  call five((a < 5 ? a : b))\n+  if (a /= 5) stop 1\n+contains\n+  subroutine five(x)\n+    integer, optional :: x\n+    if (present(x)) then\n+      x = 5\n+    end if\n+  end subroutine five\n+end program conditional_arg\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_7.f90 b/gcc/testsuite/gfortran.dg/conditional_7.f90\nnew file mode 100644\nindex 000000000000..87e621a6f74e\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_7.f90\n@@ -0,0 +1,11 @@\n+! { dg-do compile }\n+! { dg-options \"-std=f2023\" }\n+module m\n+  contains\n+    function f(n) result(str)\n+      integer, value :: n\n+      character(len=(n > 5 ? n : 5)) :: str\n+      str = \"\"\n+      str(1:5) = \"abcde\"\n+    end\n+end\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_8.f90 b/gcc/testsuite/gfortran.dg/conditional_8.f90\nnew file mode 100644\nindex 000000000000..913acc7f4a80\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_8.f90\n@@ -0,0 +1,14 @@\n+! { dg-do run }\n+! { dg-options \"-std=f2023\" }\n+implicit none\n+integer :: aa(2)\n+aa = [1, 2]\n+\n+print *, (aa(1) > 0 ? aa(2) : g())\n+contains\n+integer function g()\n+  allocatable :: g\n+  error stop \"should not be called\"\n+  g = 3\n+end\n+end\ndiff --git a/gcc/testsuite/gfortran.dg/conditional_9.f90 b/gcc/testsuite/gfortran.dg/conditional_9.f90\nnew file mode 100644\nindex 000000000000..d1bb15e63153\n--- /dev/null\n+++ b/gcc/testsuite/gfortran.dg/conditional_9.f90\n@@ -0,0 +1,11 @@\n+! { dg-do compile }\n+! { dg-options \"-std=f2023\" }\n+implicit none\n+integer :: i, j\n+do concurrent (i=(j > 1 ? 0 : 1) : 5) local(j) ! { dg-error \"must not appear in LOCAL locality-spec at\" }\n+end do\n+do concurrent (i=(.true. ? j : 1) : 5) local(j) ! { dg-error \"must not appear in LOCAL locality-spec at\" }\n+end do\n+do concurrent (i=(.false. ? 1 : j) : 5) local(j) ! { dg-error \"must not appear in LOCAL locality-spec at\" }\n+end do\n+end\n",
    "prefixes": [
        "v1",
        "1/1"
    ]
}