Teach statement / declaration disambiguation about C++11-style generalized initializers.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 20 Mar 2013 03:35:02 +0000 (03:35 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 20 Mar 2013 03:35:02 +0000 (03:35 +0000)
llvm-svn: 177480

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

index b3cf983..fe602f6 100644 (file)
@@ -184,6 +184,9 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
   return TPResult::Ambiguous();
 }
 
+/// Tentatively parse an init-declarator-list in order to disambiguate it from
+/// an expression.
+///
 ///       init-declarator-list:
 ///         init-declarator
 ///         init-declarator-list ',' init-declarator
@@ -192,14 +195,21 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
 ///         declarator initializer[opt]
 /// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
 ///
-/// initializer:
-///   '=' initializer-clause
-///   '(' expression-list ')'
+///       initializer:
+///         brace-or-equal-initializer
+///         '(' expression-list ')'
+///
+///       brace-or-equal-initializer:
+///         '=' initializer-clause
+/// [C++11] braced-init-list
 ///
-/// initializer-clause:
-///   assignment-expression
-///   '{' initializer-list ','[opt] '}'
-///   '{' '}'
+///       initializer-clause:
+///         assignment-expression
+///         braced-init-list
+///
+///       braced-init-list:
+///         '{' initializer-list ','[opt] '}'
+///         '{' '}'
 ///
 Parser::TPResult Parser::TryParseInitDeclaratorList() {
   while (1) {
@@ -218,6 +228,10 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
       ConsumeParen();
       if (!SkipUntil(tok::r_paren))
         return TPResult::Error();
+    } else if (Tok.is(tok::l_brace)) {
+      // A left-brace here is sufficient to disambiguate the parse; an
+      // expression can never be followed directly by a braced-init-list.
+      return TPResult::True();
     } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
       // MSVC and g++ won't examine the rest of declarators if '=' is 
       // encountered; they just conclude that we have a declaration.
index dac3c09..3b864f9 100644 (file)
@@ -133,3 +133,19 @@ namespace ellipsis {
     void l(int(S<int>::*...)(T)); // expected-warning {{ISO C++11 requires a parenthesized pack declaration to have a name}}
   };
 }
+
+namespace braced_init_list {
+  struct X {
+    void foo() {}
+  };
+
+  void (*pf1)() {};
+  void (X::*pmf1)() {&X::foo};
+  void (X::*pmf2)() = {&X::foo};
+
+  void test() {
+    void (*pf2)() {};
+    void (X::*pmf3)() {&X::foo};
+    void (X::*pmf4)() = {&X::foo};
+  }
+}