Author: Richard Smith Date: 2019-11-27T17:54:26-08:00 New Revision: 789a7aa37d0cca70d6e48908ce3e8bb4e761e266
URL: https://github.com/llvm/llvm-project/commit/789a7aa37d0cca70d6e48908ce3e8bb4e761e266 DIFF: https://github.com/llvm/llvm-project/commit/789a7aa37d0cca70d6e48908ce3e8bb4e761e266.diff LOG: Properly disambiguate between array declarators and array subscript expressions. Added: Modified: clang/lib/Parse/ParseTentative.cpp clang/test/Parser/cxx-ambig-decl-expr.cpp Removed: ################################################################################ diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index e2e16ca63d1e..9cc41328c469 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -2066,9 +2066,21 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { /// Parser::TPResult Parser::TryParseBracketDeclarator() { ConsumeBracket(); - if (!SkipUntil(tok::r_square, StopAtSemi)) + + // A constant-expression cannot begin with a '{', but the + // expr-or-braced-init-list of a postfix-expression can. + if (Tok.is(tok::l_brace)) + return TPResult::False; + + if (!SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch)) return TPResult::Error; + // If we hit a comma before the ']', this is not a constant-expression, + // but might still be the expr-or-braced-init-list of a postfix-expression. + if (Tok.isNot(tok::r_square)) + return TPResult::False; + + ConsumeBracket(); return TPResult::Ambiguous; } diff --git a/clang/test/Parser/cxx-ambig-decl-expr.cpp b/clang/test/Parser/cxx-ambig-decl-expr.cpp index 6507eafb74cd..02857e21f7c3 100644 --- a/clang/test/Parser/cxx-ambig-decl-expr.cpp +++ b/clang/test/Parser/cxx-ambig-decl-expr.cpp @@ -17,3 +17,25 @@ auto (*q)() -> int(*)(unknown); // expected-error {{unknown type name 'unknown'} auto (*r)() -> int(*)(unknown + 1); // expected-error {{undeclared identifier 'unknown'}} int f(unknown const x); // expected-error {{unknown type name 'unknown'}} + +// Disambiguating an array declarator from an array subscripting. +void arr() { + int x[] = {1}; // expected-note 2{{previous}} + + // This is array indexing not an array declarator because a comma expression + // is not syntactically a constant-expression. + int(x[1,1]); // expected-warning 2{{unused}} + + // This is array indexing not an array declaration because a braced-init-list + // is not syntactically a constant-expression. + int(x[{0}]); // expected-error {{array subscript is not an integer}} + struct A { + struct Q { int n; }; + int operator[](Q); + } a; + int(a[{0}]); // expected-warning {{unused}} + + // These are array declarations. + int(x[(1,1)]); // expected-error {{redefinition}} + int(x[true ? 1,1 : 1]); // expected-error {{redefinition}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits