Properly disambiguate between array declarators and array subscript expressions.
authorRichard Smith <richard@metafoo.co.uk>
Thu, 28 Nov 2019 01:54:26 +0000 (17:54 -0800)
committerRichard Smith <richard@metafoo.co.uk>
Thu, 28 Nov 2019 01:54:26 +0000 (17:54 -0800)
clang/lib/Parse/ParseTentative.cpp
clang/test/Parser/cxx-ambig-decl-expr.cpp

index e2e16ca..9cc4132 100644 (file)
@@ -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;
 }
 
index 6507eaf..02857e2 100644 (file)
@@ -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}}
+}