]> granicus.if.org Git - clang/commitdiff
If we see '(...' where we're expecting an abstract-declarator, that doesn't
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 27 Mar 2012 23:05:05 +0000 (23:05 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 27 Mar 2012 23:05:05 +0000 (23:05 +0000)
necessarily mean we've found a function declarator. If the next token is not
a ')', this is actually a parenthesized pack expansion.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153544 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseDecl.cpp
lib/Parse/ParseTentative.cpp
test/Parser/cxx0x-ambig.cpp

index 9d8aed533311b278d00c01119bc8bec39d8c13cc..9aa5eaba00ce4a28c3a89d44381451834f46399a 100644 (file)
@@ -3354,15 +3354,17 @@ bool Parser::isConstructorDeclarator() {
     return false;
   }
 
-  // Current class name must be followed by a left parentheses.
+  // Current class name must be followed by a left parenthesis.
   if (Tok.isNot(tok::l_paren)) {
     TPA.Revert();
     return false;
   }
   ConsumeParen();
 
-  // A right parentheses or ellipsis signals that we have a constructor.
-  if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) {
+  // A right parenthesis, or ellipsis followed by a right parenthesis signals
+  // that we have a constructor.
+  if (Tok.is(tok::r_paren) ||
+      (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) {
     TPA.Revert();
     return true;
   }
@@ -3948,7 +3950,8 @@ void Parser::ParseParenDeclarator(Declarator &D) {
     // paren, because we haven't seen the identifier yet.
     isGrouping = true;
   } else if (Tok.is(tok::r_paren) ||           // 'int()' is a function.
-             (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis)) || // C++ int(...)
+             (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&
+              NextToken().is(tok::r_paren)) || // C++ int(...)
              isDeclarationSpecifier()) {       // 'int(int)' is a function.
     // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
     // considered to be a type, not a K&R identifier-list.
index 1e30c7fff69c6de69efdc7e21fe8d4b47f55e260..e3b922500fc08362fc419657970d1ee54d86858e 100644 (file)
@@ -553,7 +553,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
     ConsumeParen();
     if (mayBeAbstract &&
         (Tok.is(tok::r_paren) ||       // 'int()' is a function.
-         Tok.is(tok::ellipsis) ||      // 'int(...)' is a function.
+         // 'int(...)' is a function.
+         (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
          isDeclarationSpecifier())) {   // 'int(int)' is a function.
       // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
       //        exception-specification[opt]
@@ -1236,7 +1237,10 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() {
     // '...'[opt]
     if (Tok.is(tok::ellipsis)) {
       ConsumeToken();
-      return TPResult::True(); // '...' is a sign of a function declarator.
+      if (Tok.is(tok::r_paren))
+        return TPResult::True(); // '...)' is a sign of a function declarator.
+      else
+        return TPResult::False();
     }
 
     ParsedAttributes attrs(AttrFactory);
@@ -1269,7 +1273,10 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() {
 
     if (Tok.is(tok::ellipsis)) {
       ConsumeToken();
-      return TPResult::True(); // '...' is a sign of a function declarator.
+      if (Tok.is(tok::r_paren))
+        return TPResult::True(); // '...)' is a sign of a function declarator.
+      else
+        return TPResult::False();
     }
 
     if (Tok.isNot(tok::comma))
index d4cbfeab75d80e609ab382330995dbc0e9312a64..98757b48c7162effb3b1b6000cc6ca962f6e371b 100644 (file)
@@ -100,3 +100,28 @@ namespace trailing_return {
     }
   }
 }
+
+namespace ellipsis {
+  template<typename...T>
+  struct S {
+    void e(S::S());
+    void f(S(...args[sizeof(T)])); // expected-note {{here}}
+    void f(S(...args)[sizeof(T)]); // expected-error {{redeclared}} expected-note {{here}}
+    void f(S ...args[sizeof(T)]); // expected-error {{redeclared}}
+    void g(S(...[sizeof(T)])); // expected-note {{here}}
+    void g(S(...)[sizeof(T)]); // expected-error {{function cannot return array type}}
+    void g(S ...[sizeof(T)]); // expected-error {{redeclared}}
+    void h(T(...)); // function type, expected-error {{unexpanded parameter pack}}
+    void h(T...); // pack expansion, ok
+    void i(int(T...)); // expected-note {{here}}
+    void i(int(T...a)); // expected-error {{redeclared}}
+    void i(int(T, ...)); // function type, expected-error {{unexpanded parameter pack}}
+    void i(int(T, ...a)); // expected-error {{expected ')'}} expected-note {{to match}} expected-error {{unexpanded parameter pack}}
+    void j(int(int...)); // function type, ok
+    void j(int(int...a)); // expected-error {{does not contain any unexpanded parameter packs}}
+    void j(T(int...)); // expected-error {{unexpanded parameter pack}}
+    void j(T(T...)); // expected-error {{unexpanded parameter pack}}
+    void k(int(...)(T)); // expected-error {{cannot return function type}}
+    void k(int ...(T));
+  };
+}