aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTentative.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseTentative.cpp')
-rw-r--r--lib/Parse/ParseTentative.cpp43
1 files changed, 32 insertions, 11 deletions
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index b3cf983bbc..dff3b64c5b 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -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.
@@ -823,11 +837,12 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw___underlying_type:
- case tok::kw_thread_local:
case tok::kw__Decimal32:
case tok::kw__Decimal64:
case tok::kw__Decimal128:
case tok::kw___thread:
+ case tok::kw_thread_local:
+ case tok::kw__Thread_local:
case tok::kw_typeof:
case tok::kw___cdecl:
case tok::kw___stdcall:
@@ -879,7 +894,7 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
/// function-specifier
/// 'friend'
/// 'typedef'
-/// [C++0x] 'constexpr'
+/// [C++11] 'constexpr'
/// [GNU] attributes declaration-specifiers[opt]
///
/// storage-class-specifier:
@@ -889,6 +904,8 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
/// 'mutable'
/// 'auto'
/// [GNU] '__thread'
+/// [C++11] 'thread_local'
+/// [C11] '_Thread_local'
///
/// function-specifier:
/// 'inline'
@@ -923,8 +940,9 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
/// 'void'
/// [GNU] typeof-specifier
/// [GNU] '_Complex'
-/// [C++0x] 'auto' [TODO]
-/// [C++0x] 'decltype' ( expression )
+/// [C++11] 'auto'
+/// [C++11] 'decltype' ( expression )
+/// [C++1y] 'decltype' ( 'auto' )
///
/// type-name:
/// class-name
@@ -985,6 +1003,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// to types and identifiers, in order to try to recover from errors.
CorrectionCandidateCallback TypoCorrection;
TypoCorrection.WantRemainingKeywords = false;
+ TypoCorrection.WantTypeSpecifiers = Next.isNot(tok::arrow);
switch (TryAnnotateName(false /* no nested name specifier */,
&TypoCorrection)) {
case ANK_Error:
@@ -1058,6 +1077,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_mutable:
case tok::kw_auto:
case tok::kw___thread:
+ case tok::kw_thread_local:
+ case tok::kw__Thread_local:
// function-specifier
case tok::kw_inline:
case tok::kw_virtual: