From 8cf28585a40311163a08840beee035097638d41d Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Tue, 28 Jun 2022 01:13:04 +0200 Subject: [PATCH] [pseudo] Allow mixed designated/undesignated init lists. This isn't allowed by the standard grammar but is allowed in C, and clang/GCC permit it as an extension. It avoids the need to determine which type of list we have in error-recovery. While here, also support array index designators `{ [4]=1 }` which are also legal in C, and common extensions in C++. Differential Revision: https://reviews.llvm.org/D128687 --- clang-tools-extra/pseudo/lib/cxx.bnf | 19 +++++++++------ .../pseudo/test/cxx/mixed-designator.cpp | 27 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 clang-tools-extra/pseudo/test/cxx/mixed-designator.cpp diff --git a/clang-tools-extra/pseudo/lib/cxx.bnf b/clang-tools-extra/pseudo/lib/cxx.bnf index ec05af9..aa243db 100644 --- a/clang-tools-extra/pseudo/lib/cxx.bnf +++ b/clang-tools-extra/pseudo/lib/cxx.bnf @@ -158,7 +158,10 @@ postfix-expression := REINTERPRET_CAST < type-id > ( expression ) postfix-expression := CONST_CAST < type-id > ( expression ) postfix-expression := TYPEID ( expression ) postfix-expression := TYPEID ( type-id ) -expression-list := initializer-list +#! Standard defines expression-list in terms of initializer-list, but our +# initializer-list allows designators. +expression-list := initializer-clause ..._opt +expression-list := expression-list , initializer-clause ..._opt # expr.unary unary-expression := postfix-expression unary-expression := unary-operator cast-expression @@ -453,15 +456,17 @@ brace-or-equal-initializer := = initializer-clause brace-or-equal-initializer := braced-init-list initializer-clause := assignment-expression initializer-clause := braced-init-list +#! Allow mixed designated/non-designated init-list. +# This is standard C, and accepted by clang and others as an extension. braced-init-list := { initializer-list ,_opt } -braced-init-list := { designated-initializer-list ,_opt } braced-init-list := { } -initializer-list := initializer-clause ..._opt -initializer-list := initializer-list , initializer-clause ..._opt -designated-initializer-list := designated-initializer-clause -designated-initializer-list := designated-initializer-list , designated-initializer-clause -designated-initializer-clause := designator brace-or-equal-initializer +initializer-list := initializer-list-item ..._opt +initializer-list := initializer-list , initializer-list-item ..._opt +initializer-list-item := initializer-clause +initializer-list-item := designator brace-or-equal-initializer designator := . IDENTIFIER +#! Array designators are legal in C, and a common extension in C++. +designator := [ expression ] expr-or-braced-init-list := expression expr-or-braced-init-list := braced-init-list # dcl.fct diff --git a/clang-tools-extra/pseudo/test/cxx/mixed-designator.cpp b/clang-tools-extra/pseudo/test/cxx/mixed-designator.cpp new file mode 100644 index 0000000..ec56839 --- /dev/null +++ b/clang-tools-extra/pseudo/test/cxx/mixed-designator.cpp @@ -0,0 +1,27 @@ +// RUN: clang-pseudo -grammar=%cxx-bnf-file -source=%s --print-forest | FileCheck %s +// FIXME: tighten CHECK to CHECK-NEXT once numeric literals are unambiguous. +auto x = { 1, .f = 2, [c]{3} }; +// CHECK: initializer-clause~braced-init-list +// CHECK-NEXT: ├─{ := tok[3] +// CHECK-NEXT: ├─initializer-list +// CHECK-NEXT: │ ├─initializer-list +// CHECK-NEXT: │ │ ├─initializer-list~literal +// CHECK: │ │ ├─, := tok[5] +// CHECK-NEXT: │ │ └─initializer-list-item +// CHECK-NEXT: │ │ ├─designator +// CHECK-NEXT: │ │ │ ├─. := tok[6] +// CHECK-NEXT: │ │ │ └─IDENTIFIER := tok[7] +// CHECK-NEXT: │ │ └─brace-or-equal-initializer +// CHECK-NEXT: │ │ ├─= := tok[8] +// CHECK-NEXT: │ │ └─initializer-clause~literal +// CHECK: │ ├─, := tok[10] +// CHECK-NEXT: │ └─initializer-list-item +// CHECK-NEXT: │ ├─designator +// CHECK-NEXT: │ │ ├─[ := tok[11] +// CHECK-NEXT: │ │ ├─expression~IDENTIFIER := tok[12] +// CHECK-NEXT: │ │ └─] := tok[13] +// CHECK-NEXT: │ └─brace-or-equal-initializer~braced-init-list +// CHECK-NEXT: │ ├─{ := tok[14] +// CHECK-NEXT: │ ├─initializer-list~literal +// CHECK: │ └─} := tok[16] +// CHECK-NEXT: └─} := tok[17] -- 2.7.4