diff --git a/clang-tools-extra/pseudo/lib/cxx.bnf b/clang-tools-extra/pseudo/lib/cxx.bnf --- a/clang-tools-extra/pseudo/lib/cxx.bnf +++ b/clang-tools-extra/pseudo/lib/cxx.bnf @@ -158,7 +158,10 @@ 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 := 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 --- /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]