Update parser's disambiguation to cope with braced function-style casts in
C++11, and with braced-init-list initializers in conditions. This exposed an
ambiguity with enum underlying types versus bitfields, which we resolve by
treating 'enum E : T {' as always defining an enumeration (even if it would
only successfully parse as a bitfield). This appears to be g++ compatible.
llvm-svn: 151227
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 987ae65d..35c418c 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -233,6 +233,8 @@
/// condition:
/// expression
/// type-specifier-seq declarator '=' assignment-expression
+/// [C++11] type-specifier-seq declarator '=' initializer-clause
+/// [C++11] type-specifier-seq declarator braced-init-list
/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
/// '=' assignment-expression
///
@@ -274,6 +276,8 @@
if (Tok.is(tok::equal) ||
Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
TPR = TPResult::True();
+ else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace))
+ TPR = TPResult::True();
else
TPR = TPResult::False();
}
@@ -834,7 +838,8 @@
/// 'volatile'
/// [GNU] restrict
///
-Parser::TPResult Parser::isCXXDeclarationSpecifier() {
+Parser::TPResult
+Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult) {
switch (Tok.getKind()) {
case tok::identifier: // foo::bar
// Check for need to substitute AltiVec __vector keyword
@@ -849,7 +854,7 @@
return TPResult::Error();
if (Tok.is(tok::identifier))
return TPResult::False();
- return isCXXDeclarationSpecifier();
+ return isCXXDeclarationSpecifier(BracedCastResult);
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
@@ -863,7 +868,7 @@
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return TPResult::Error();
- return isCXXDeclarationSpecifier();
+ return isCXXDeclarationSpecifier(BracedCastResult);
// decl-specifier:
// storage-class-specifier
@@ -965,7 +970,7 @@
bool isIdentifier = Tok.is(tok::identifier);
TPResult TPR = TPResult::False();
if (!isIdentifier)
- TPR = isCXXDeclarationSpecifier();
+ TPR = isCXXDeclarationSpecifier(BracedCastResult);
PA.Revert();
if (isIdentifier ||
@@ -1005,6 +1010,7 @@
TPResult TPR = TryParseProtocolQualifiers();
bool isFollowedByParen = Tok.is(tok::l_paren);
+ bool isFollowedByBrace = Tok.is(tok::l_brace);
PA.Revert();
@@ -1013,6 +1019,9 @@
if (isFollowedByParen)
return TPResult::Ambiguous();
+
+ if (getLang().CPlusPlus0x && isFollowedByBrace)
+ return BracedCastResult;
return TPResult::True();
}
@@ -1036,6 +1045,15 @@
if (NextToken().is(tok::l_paren))
return TPResult::Ambiguous();
+ // This is a function-style cast in all cases we disambiguate other than
+ // one:
+ // struct S {
+ // enum E : int { a = 4 }; // enum
+ // enum E : int { 4 }; // bit-field
+ // };
+ if (getLang().CPlusPlus0x && NextToken().is(tok::l_brace))
+ return BracedCastResult;
+
if (isStartOfObjCClassMessageMissingOpenBracket())
return TPResult::False();
@@ -1050,6 +1068,7 @@
TPResult TPR = TryParseTypeofSpecifier();
bool isFollowedByParen = Tok.is(tok::l_paren);
+ bool isFollowedByBrace = Tok.is(tok::l_brace);
PA.Revert();
@@ -1059,6 +1078,9 @@
if (isFollowedByParen)
return TPResult::Ambiguous();
+ if (getLang().CPlusPlus0x && isFollowedByBrace)
+ return BracedCastResult;
+
return TPResult::True();
}
@@ -1219,6 +1241,8 @@
MaybeParseMicrosoftAttributes(attrs);
// decl-specifier-seq
+ // A parameter-declaration's initializer must be preceded by an '=', so
+ // decl-specifier-seq '{' is not a parameter in C++11.
TPResult TPR = TryParseDeclarationSpecifier();
if (TPR != TPResult::Ambiguous())
return TPR;