ParseTentative.cpp revision 212904
1193326Sed//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements the tentative parsing portions of the Parser
11193326Sed//  interfaces, for ambiguity resolution.
12193326Sed//
13193326Sed//===----------------------------------------------------------------------===//
14193326Sed
15193326Sed#include "clang/Parse/Parser.h"
16193326Sed#include "clang/Parse/ParseDiagnostic.h"
17212904Sdim#include "clang/Sema/ParsedTemplate.h"
18193326Sedusing namespace clang;
19193326Sed
20193326Sed/// isCXXDeclarationStatement - C++-specialized function that disambiguates
21193326Sed/// between a declaration or an expression statement, when parsing function
22193326Sed/// bodies. Returns true for declaration, false for expression.
23193326Sed///
24193326Sed///         declaration-statement:
25193326Sed///           block-declaration
26193326Sed///
27193326Sed///         block-declaration:
28193326Sed///           simple-declaration
29193326Sed///           asm-definition
30193326Sed///           namespace-alias-definition
31193326Sed///           using-declaration
32193326Sed///           using-directive
33193326Sed/// [C++0x]   static_assert-declaration
34193326Sed///
35193326Sed///         asm-definition:
36193326Sed///           'asm' '(' string-literal ')' ';'
37193326Sed///
38193326Sed///         namespace-alias-definition:
39193326Sed///           'namespace' identifier = qualified-namespace-specifier ';'
40193326Sed///
41193326Sed///         using-declaration:
42193326Sed///           'using' typename[opt] '::'[opt] nested-name-specifier
43193326Sed///                 unqualified-id ';'
44193326Sed///           'using' '::' unqualified-id ;
45193326Sed///
46193326Sed///         using-directive:
47193326Sed///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
48193326Sed///                 namespace-name ';'
49193326Sed///
50193326Sedbool Parser::isCXXDeclarationStatement() {
51193326Sed  switch (Tok.getKind()) {
52193326Sed    // asm-definition
53193326Sed  case tok::kw_asm:
54193326Sed    // namespace-alias-definition
55193326Sed  case tok::kw_namespace:
56193326Sed    // using-declaration
57193326Sed    // using-directive
58193326Sed  case tok::kw_using:
59199990Srdivacky    // static_assert-declaration
60193326Sed  case tok::kw_static_assert:
61193326Sed    return true;
62199990Srdivacky    // simple-declaration
63193326Sed  default:
64193326Sed    return isCXXSimpleDeclaration();
65193326Sed  }
66193326Sed}
67193326Sed
68193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
69193326Sed/// between a simple-declaration or an expression-statement.
70193326Sed/// If during the disambiguation process a parsing error is encountered,
71193326Sed/// the function returns true to let the declaration parsing code handle it.
72193326Sed/// Returns false if the statement is disambiguated as expression.
73193326Sed///
74193326Sed/// simple-declaration:
75193326Sed///   decl-specifier-seq init-declarator-list[opt] ';'
76193326Sed///
77193326Sedbool Parser::isCXXSimpleDeclaration() {
78193326Sed  // C++ 6.8p1:
79193326Sed  // There is an ambiguity in the grammar involving expression-statements and
80193326Sed  // declarations: An expression-statement with a function-style explicit type
81193326Sed  // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
82193326Sed  // from a declaration where the first declarator starts with a '('. In those
83193326Sed  // cases the statement is a declaration. [Note: To disambiguate, the whole
84193326Sed  // statement might have to be examined to determine if it is an
85193326Sed  // expression-statement or a declaration].
86193326Sed
87193326Sed  // C++ 6.8p3:
88193326Sed  // The disambiguation is purely syntactic; that is, the meaning of the names
89193326Sed  // occurring in such a statement, beyond whether they are type-names or not,
90193326Sed  // is not generally used in or changed by the disambiguation. Class
91193326Sed  // templates are instantiated as necessary to determine if a qualified name
92193326Sed  // is a type-name. Disambiguation precedes parsing, and a statement
93193326Sed  // disambiguated as a declaration may be an ill-formed declaration.
94193326Sed
95193326Sed  // We don't have to parse all of the decl-specifier-seq part. There's only
96193326Sed  // an ambiguity if the first decl-specifier is
97193326Sed  // simple-type-specifier/typename-specifier followed by a '(', which may
98193326Sed  // indicate a function-style cast expression.
99193326Sed  // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
100193326Sed  // a case.
101193326Sed
102193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
103193326Sed  if (TPR != TPResult::Ambiguous())
104193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
105193326Sed                                     // TPResult::Error().
106193326Sed
107193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
108193326Sed  // and how they were resolved (number of declarations+number of expressions).
109193326Sed
110193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
111193326Sed  // We need tentative parsing...
112193326Sed
113193326Sed  TentativeParsingAction PA(*this);
114193326Sed
115193326Sed  TPR = TryParseSimpleDeclaration();
116193326Sed  SourceLocation TentativeParseLoc = Tok.getLocation();
117193326Sed
118193326Sed  PA.Revert();
119193326Sed
120193326Sed  // In case of an error, let the declaration parsing code handle it.
121193326Sed  if (TPR == TPResult::Error())
122193326Sed    return true;
123193326Sed
124193326Sed  // Declarations take precedence over expressions.
125193326Sed  if (TPR == TPResult::Ambiguous())
126193326Sed    TPR = TPResult::True();
127193326Sed
128193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
129193326Sed  return TPR == TPResult::True();
130193326Sed}
131193326Sed
132193326Sed/// simple-declaration:
133193326Sed///   decl-specifier-seq init-declarator-list[opt] ';'
134193326Sed///
135193326SedParser::TPResult Parser::TryParseSimpleDeclaration() {
136193326Sed  // We know that we have a simple-type-specifier/typename-specifier followed
137193326Sed  // by a '('.
138193326Sed  assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
139193326Sed
140193326Sed  if (Tok.is(tok::kw_typeof))
141193326Sed    TryParseTypeofSpecifier();
142193326Sed  else
143193326Sed    ConsumeToken();
144193326Sed
145193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
146193326Sed
147193326Sed  TPResult TPR = TryParseInitDeclaratorList();
148193326Sed  if (TPR != TPResult::Ambiguous())
149193326Sed    return TPR;
150193326Sed
151193326Sed  if (Tok.isNot(tok::semi))
152193326Sed    return TPResult::False();
153193326Sed
154193326Sed  return TPResult::Ambiguous();
155193326Sed}
156193326Sed
157193326Sed///       init-declarator-list:
158193326Sed///         init-declarator
159193326Sed///         init-declarator-list ',' init-declarator
160193326Sed///
161193326Sed///       init-declarator:
162193326Sed///         declarator initializer[opt]
163193326Sed/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
164193326Sed///
165193326Sed/// initializer:
166193326Sed///   '=' initializer-clause
167193326Sed///   '(' expression-list ')'
168193326Sed///
169193326Sed/// initializer-clause:
170193326Sed///   assignment-expression
171193326Sed///   '{' initializer-list ','[opt] '}'
172193326Sed///   '{' '}'
173193326Sed///
174193326SedParser::TPResult Parser::TryParseInitDeclaratorList() {
175193326Sed  while (1) {
176193326Sed    // declarator
177193326Sed    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
178193326Sed    if (TPR != TPResult::Ambiguous())
179193326Sed      return TPR;
180193326Sed
181193326Sed    // [GNU] simple-asm-expr[opt] attributes[opt]
182193326Sed    if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
183193326Sed      return TPResult::True();
184193326Sed
185193326Sed    // initializer[opt]
186193326Sed    if (Tok.is(tok::l_paren)) {
187193326Sed      // Parse through the parens.
188193326Sed      ConsumeParen();
189193326Sed      if (!SkipUntil(tok::r_paren))
190193326Sed        return TPResult::Error();
191212904Sdim    } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
192212904Sdim      // MSVC and g++ won't examine the rest of declarators if '=' is
193212904Sdim      // encountered; they just conclude that we have a declaration.
194212904Sdim      // EDG parses the initializer completely, which is the proper behavior
195212904Sdim      // for this case.
196193326Sed      //
197212904Sdim      // At present, Clang follows MSVC and g++, since the parser does not have
198212904Sdim      // the ability to parse an expression fully without recording the
199212904Sdim      // results of that parse.
200212904Sdim      // Also allow 'in' after on objective-c declaration as in:
201212904Sdim      // for (int (^b)(void) in array). Ideally this should be done in the
202212904Sdim      // context of parsing for-init-statement of a foreach statement only. But,
203212904Sdim      // in any other context 'in' is invalid after a declaration and parser
204212904Sdim      // issues the error regardless of outcome of this decision.
205212904Sdim      // FIXME. Change if above assumption does not hold.
206212904Sdim      return TPResult::True();
207193326Sed    }
208193326Sed
209193326Sed    if (Tok.isNot(tok::comma))
210193326Sed      break;
211193326Sed    ConsumeToken(); // the comma.
212193326Sed  }
213193326Sed
214193326Sed  return TPResult::Ambiguous();
215193326Sed}
216193326Sed
217193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an
218193326Sed/// expression for a condition of a if/switch/while/for statement.
219193326Sed/// If during the disambiguation process a parsing error is encountered,
220193326Sed/// the function returns true to let the declaration parsing code handle it.
221193326Sed///
222193326Sed///       condition:
223193326Sed///         expression
224193326Sed///         type-specifier-seq declarator '=' assignment-expression
225193326Sed/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
226193326Sed///             '=' assignment-expression
227193326Sed///
228193326Sedbool Parser::isCXXConditionDeclaration() {
229193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
230193326Sed  if (TPR != TPResult::Ambiguous())
231193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
232193326Sed                                     // TPResult::Error().
233193326Sed
234193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
235193326Sed  // and how they were resolved (number of declarations+number of expressions).
236193326Sed
237193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
238193326Sed  // We need tentative parsing...
239193326Sed
240193326Sed  TentativeParsingAction PA(*this);
241193326Sed
242193326Sed  // type-specifier-seq
243193326Sed  if (Tok.is(tok::kw_typeof))
244193326Sed    TryParseTypeofSpecifier();
245193326Sed  else
246193326Sed    ConsumeToken();
247193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
248193326Sed
249193326Sed  // declarator
250193326Sed  TPR = TryParseDeclarator(false/*mayBeAbstract*/);
251193326Sed
252193326Sed  // In case of an error, let the declaration parsing code handle it.
253193326Sed  if (TPR == TPResult::Error())
254193326Sed    TPR = TPResult::True();
255193326Sed
256193326Sed  if (TPR == TPResult::Ambiguous()) {
257193326Sed    // '='
258193326Sed    // [GNU] simple-asm-expr[opt] attributes[opt]
259193326Sed    if (Tok.is(tok::equal)  ||
260193326Sed        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
261193326Sed      TPR = TPResult::True();
262193326Sed    else
263193326Sed      TPR = TPResult::False();
264193326Sed  }
265193326Sed
266193326Sed  PA.Revert();
267193326Sed
268193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
269193326Sed  return TPR == TPResult::True();
270193326Sed}
271193326Sed
272198092Srdivacky  /// \brief Determine whether the next set of tokens contains a type-id.
273193326Sed  ///
274193326Sed  /// The context parameter states what context we're parsing right
275193326Sed  /// now, which affects how this routine copes with the token
276193326Sed  /// following the type-id. If the context is TypeIdInParens, we have
277193326Sed  /// already parsed the '(' and we will cease lookahead when we hit
278193326Sed  /// the corresponding ')'. If the context is
279193326Sed  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
280193326Sed  /// before this template argument, and will cease lookahead when we
281193326Sed  /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
282193326Sed  /// and false for an expression.  If during the disambiguation
283193326Sed  /// process a parsing error is encountered, the function returns
284193326Sed  /// true to let the declaration parsing code handle it.
285193326Sed  ///
286193326Sed  /// type-id:
287193326Sed  ///   type-specifier-seq abstract-declarator[opt]
288193326Sed  ///
289193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
290198092Srdivacky
291193326Sed  isAmbiguous = false;
292193326Sed
293193326Sed  // C++ 8.2p2:
294193326Sed  // The ambiguity arising from the similarity between a function-style cast and
295193326Sed  // a type-id can occur in different contexts. The ambiguity appears as a
296193326Sed  // choice between a function-style cast expression and a declaration of a
297193326Sed  // type. The resolution is that any construct that could possibly be a type-id
298193326Sed  // in its syntactic context shall be considered a type-id.
299193326Sed
300193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
301193326Sed  if (TPR != TPResult::Ambiguous())
302193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
303193326Sed                                     // TPResult::Error().
304193326Sed
305193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
306193326Sed  // and how they were resolved (number of declarations+number of expressions).
307193326Sed
308193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
309193326Sed  // We need tentative parsing...
310193326Sed
311193326Sed  TentativeParsingAction PA(*this);
312193326Sed
313193326Sed  // type-specifier-seq
314193326Sed  if (Tok.is(tok::kw_typeof))
315193326Sed    TryParseTypeofSpecifier();
316193326Sed  else
317193326Sed    ConsumeToken();
318193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
319193326Sed
320193326Sed  // declarator
321193326Sed  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
322193326Sed
323193326Sed  // In case of an error, let the declaration parsing code handle it.
324193326Sed  if (TPR == TPResult::Error())
325193326Sed    TPR = TPResult::True();
326193326Sed
327193326Sed  if (TPR == TPResult::Ambiguous()) {
328193326Sed    // We are supposed to be inside parens, so if after the abstract declarator
329193326Sed    // we encounter a ')' this is a type-id, otherwise it's an expression.
330193326Sed    if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
331193326Sed      TPR = TPResult::True();
332193326Sed      isAmbiguous = true;
333193326Sed
334193326Sed    // We are supposed to be inside a template argument, so if after
335193326Sed    // the abstract declarator we encounter a '>', '>>' (in C++0x), or
336193326Sed    // ',', this is a type-id. Otherwise, it's an expression.
337193326Sed    } else if (Context == TypeIdAsTemplateArgument &&
338193326Sed               (Tok.is(tok::greater) || Tok.is(tok::comma) ||
339193326Sed                (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
340193326Sed      TPR = TPResult::True();
341193326Sed      isAmbiguous = true;
342193326Sed
343193326Sed    } else
344193326Sed      TPR = TPResult::False();
345193326Sed  }
346193326Sed
347193326Sed  PA.Revert();
348193326Sed
349193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
350193326Sed  return TPR == TPResult::True();
351193326Sed}
352193326Sed
353199990Srdivacky/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
354199990Srdivacky/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
355199990Srdivacky/// performed that will simply return true if a [[ is seen. Currently C++ has no
356199990Srdivacky/// syntactical ambiguities from this check, but it may inhibit error recovery.
357199990Srdivacky/// If CheckClosing is true, a check is made for closing ]] brackets.
358199990Srdivacky///
359199990Srdivacky/// If given, After is set to the token after the attribute-specifier so that
360199990Srdivacky/// appropriate parsing decisions can be made; it is left untouched if false is
361199990Srdivacky/// returned.
362199990Srdivacky///
363199990Srdivacky/// FIXME: If an error is in the closing ]] brackets, the program assumes
364199990Srdivacky/// the absence of an attribute-specifier, which can cause very yucky errors
365199990Srdivacky/// to occur.
366199990Srdivacky///
367199990Srdivacky/// [C++0x] attribute-specifier:
368199990Srdivacky///         '[' '[' attribute-list ']' ']'
369199990Srdivacky///
370199990Srdivacky/// [C++0x] attribute-list:
371199990Srdivacky///         attribute[opt]
372199990Srdivacky///         attribute-list ',' attribute[opt]
373199990Srdivacky///
374199990Srdivacky/// [C++0x] attribute:
375199990Srdivacky///         attribute-token attribute-argument-clause[opt]
376199990Srdivacky///
377199990Srdivacky/// [C++0x] attribute-token:
378199990Srdivacky///         identifier
379199990Srdivacky///         attribute-scoped-token
380199990Srdivacky///
381199990Srdivacky/// [C++0x] attribute-scoped-token:
382199990Srdivacky///         attribute-namespace '::' identifier
383199990Srdivacky///
384199990Srdivacky/// [C++0x] attribute-namespace:
385199990Srdivacky///         identifier
386199990Srdivacky///
387199990Srdivacky/// [C++0x] attribute-argument-clause:
388199990Srdivacky///         '(' balanced-token-seq ')'
389199990Srdivacky///
390199990Srdivacky/// [C++0x] balanced-token-seq:
391199990Srdivacky///         balanced-token
392199990Srdivacky///         balanced-token-seq balanced-token
393199990Srdivacky///
394199990Srdivacky/// [C++0x] balanced-token:
395199990Srdivacky///         '(' balanced-token-seq ')'
396199990Srdivacky///         '[' balanced-token-seq ']'
397199990Srdivacky///         '{' balanced-token-seq '}'
398199990Srdivacky///         any token but '(', ')', '[', ']', '{', or '}'
399199990Srdivackybool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
400199990Srdivacky                                        tok::TokenKind *After) {
401199990Srdivacky  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
402199990Srdivacky    return false;
403199990Srdivacky
404199990Srdivacky  // No tentative parsing if we don't need to look for ]]
405199990Srdivacky  if (!CheckClosing && !getLang().ObjC1)
406199990Srdivacky    return true;
407199990Srdivacky
408199990Srdivacky  struct TentativeReverter {
409199990Srdivacky    TentativeParsingAction PA;
410199990Srdivacky
411199990Srdivacky    TentativeReverter (Parser& P)
412199990Srdivacky      : PA(P)
413199990Srdivacky    {}
414199990Srdivacky    ~TentativeReverter () {
415199990Srdivacky      PA.Revert();
416199990Srdivacky    }
417199990Srdivacky  } R(*this);
418199990Srdivacky
419199990Srdivacky  // Opening brackets were checked for above.
420199990Srdivacky  ConsumeBracket();
421199990Srdivacky  ConsumeBracket();
422199990Srdivacky
423199990Srdivacky  // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
424199990Srdivacky  SkipUntil(tok::r_square, false);
425199990Srdivacky
426199990Srdivacky  if (Tok.isNot(tok::r_square))
427199990Srdivacky    return false;
428199990Srdivacky  ConsumeBracket();
429199990Srdivacky
430199990Srdivacky  if (After)
431199990Srdivacky    *After = Tok.getKind();
432199990Srdivacky
433199990Srdivacky  return true;
434199990Srdivacky}
435199990Srdivacky
436193326Sed///         declarator:
437193326Sed///           direct-declarator
438193326Sed///           ptr-operator declarator
439193326Sed///
440193326Sed///         direct-declarator:
441193326Sed///           declarator-id
442193326Sed///           direct-declarator '(' parameter-declaration-clause ')'
443193326Sed///                 cv-qualifier-seq[opt] exception-specification[opt]
444193326Sed///           direct-declarator '[' constant-expression[opt] ']'
445193326Sed///           '(' declarator ')'
446193326Sed/// [GNU]     '(' attributes declarator ')'
447193326Sed///
448193326Sed///         abstract-declarator:
449193326Sed///           ptr-operator abstract-declarator[opt]
450193326Sed///           direct-abstract-declarator
451193326Sed///
452193326Sed///         direct-abstract-declarator:
453193326Sed///           direct-abstract-declarator[opt]
454193326Sed///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
455193326Sed///                 exception-specification[opt]
456193326Sed///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
457193326Sed///           '(' abstract-declarator ')'
458193326Sed///
459193326Sed///         ptr-operator:
460193326Sed///           '*' cv-qualifier-seq[opt]
461193326Sed///           '&'
462193326Sed/// [C++0x]   '&&'                                                        [TODO]
463193326Sed///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
464193326Sed///
465193326Sed///         cv-qualifier-seq:
466193326Sed///           cv-qualifier cv-qualifier-seq[opt]
467193326Sed///
468193326Sed///         cv-qualifier:
469193326Sed///           'const'
470193326Sed///           'volatile'
471193326Sed///
472193326Sed///         declarator-id:
473193326Sed///           id-expression
474193326Sed///
475193326Sed///         id-expression:
476193326Sed///           unqualified-id
477193326Sed///           qualified-id                                                [TODO]
478193326Sed///
479193326Sed///         unqualified-id:
480193326Sed///           identifier
481193326Sed///           operator-function-id                                        [TODO]
482193326Sed///           conversion-function-id                                      [TODO]
483193326Sed///           '~' class-name                                              [TODO]
484193326Sed///           template-id                                                 [TODO]
485193326Sed///
486193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
487193326Sed                                            bool mayHaveIdentifier) {
488193326Sed  // declarator:
489193326Sed  //   direct-declarator
490193326Sed  //   ptr-operator declarator
491193326Sed
492193326Sed  while (1) {
493193326Sed    if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
494204643Srdivacky      if (TryAnnotateCXXScopeToken(true))
495204643Srdivacky        return TPResult::Error();
496193326Sed
497193326Sed    if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
498193326Sed        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
499193326Sed      // ptr-operator
500193326Sed      ConsumeToken();
501193326Sed      while (Tok.is(tok::kw_const)    ||
502193326Sed             Tok.is(tok::kw_volatile) ||
503193326Sed             Tok.is(tok::kw_restrict))
504193326Sed        ConsumeToken();
505193326Sed    } else {
506193326Sed      break;
507193326Sed    }
508193326Sed  }
509193326Sed
510193326Sed  // direct-declarator:
511193326Sed  // direct-abstract-declarator:
512193326Sed
513198092Srdivacky  if ((Tok.is(tok::identifier) ||
514198092Srdivacky       (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
515198092Srdivacky      mayHaveIdentifier) {
516193326Sed    // declarator-id
517198092Srdivacky    if (Tok.is(tok::annot_cxxscope))
518198092Srdivacky      ConsumeToken();
519193326Sed    ConsumeToken();
520193326Sed  } else if (Tok.is(tok::l_paren)) {
521193326Sed    ConsumeParen();
522193326Sed    if (mayBeAbstract &&
523193326Sed        (Tok.is(tok::r_paren) ||       // 'int()' is a function.
524193326Sed         Tok.is(tok::ellipsis) ||      // 'int(...)' is a function.
525193326Sed         isDeclarationSpecifier())) {   // 'int(int)' is a function.
526193326Sed      // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
527193326Sed      //        exception-specification[opt]
528193326Sed      TPResult TPR = TryParseFunctionDeclarator();
529193326Sed      if (TPR != TPResult::Ambiguous())
530193326Sed        return TPR;
531193326Sed    } else {
532193326Sed      // '(' declarator ')'
533193326Sed      // '(' attributes declarator ')'
534193326Sed      // '(' abstract-declarator ')'
535193326Sed      if (Tok.is(tok::kw___attribute))
536193326Sed        return TPResult::True(); // attributes indicate declaration
537193326Sed      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
538193326Sed      if (TPR != TPResult::Ambiguous())
539193326Sed        return TPR;
540193326Sed      if (Tok.isNot(tok::r_paren))
541193326Sed        return TPResult::False();
542193326Sed      ConsumeParen();
543193326Sed    }
544193326Sed  } else if (!mayBeAbstract) {
545193326Sed    return TPResult::False();
546193326Sed  }
547193326Sed
548193326Sed  while (1) {
549193326Sed    TPResult TPR(TPResult::Ambiguous());
550193326Sed
551193326Sed    if (Tok.is(tok::l_paren)) {
552193326Sed      // Check whether we have a function declarator or a possible ctor-style
553193326Sed      // initializer that follows the declarator. Note that ctor-style
554193326Sed      // initializers are not possible in contexts where abstract declarators
555193326Sed      // are allowed.
556193326Sed      if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/))
557193326Sed        break;
558193326Sed
559193326Sed      // direct-declarator '(' parameter-declaration-clause ')'
560193326Sed      //        cv-qualifier-seq[opt] exception-specification[opt]
561193326Sed      ConsumeParen();
562193326Sed      TPR = TryParseFunctionDeclarator();
563193326Sed    } else if (Tok.is(tok::l_square)) {
564193326Sed      // direct-declarator '[' constant-expression[opt] ']'
565193326Sed      // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
566193326Sed      TPR = TryParseBracketDeclarator();
567193326Sed    } else {
568193326Sed      break;
569193326Sed    }
570193326Sed
571193326Sed    if (TPR != TPResult::Ambiguous())
572193326Sed      return TPR;
573193326Sed  }
574193326Sed
575193326Sed  return TPResult::Ambiguous();
576193326Sed}
577193326Sed
578193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
579193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
580193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error()
581193326Sed/// if a parsing error was found and reported.
582193326Sed///
583193326Sed///         decl-specifier:
584193326Sed///           storage-class-specifier
585193326Sed///           type-specifier
586193326Sed///           function-specifier
587193326Sed///           'friend'
588193326Sed///           'typedef'
589198954Srdivacky/// [C++0x]   'constexpr'
590193326Sed/// [GNU]     attributes declaration-specifiers[opt]
591193326Sed///
592193326Sed///         storage-class-specifier:
593193326Sed///           'register'
594193326Sed///           'static'
595193326Sed///           'extern'
596193326Sed///           'mutable'
597193326Sed///           'auto'
598193326Sed/// [GNU]     '__thread'
599193326Sed///
600193326Sed///         function-specifier:
601193326Sed///           'inline'
602193326Sed///           'virtual'
603193326Sed///           'explicit'
604193326Sed///
605193326Sed///         typedef-name:
606193326Sed///           identifier
607193326Sed///
608193326Sed///         type-specifier:
609193326Sed///           simple-type-specifier
610193326Sed///           class-specifier
611193326Sed///           enum-specifier
612193326Sed///           elaborated-type-specifier
613193326Sed///           typename-specifier
614193326Sed///           cv-qualifier
615193326Sed///
616193326Sed///         simple-type-specifier:
617193326Sed///           '::'[opt] nested-name-specifier[opt] type-name
618193326Sed///           '::'[opt] nested-name-specifier 'template'
619193326Sed///                 simple-template-id                              [TODO]
620193326Sed///           'char'
621193326Sed///           'wchar_t'
622193326Sed///           'bool'
623193326Sed///           'short'
624193326Sed///           'int'
625193326Sed///           'long'
626193326Sed///           'signed'
627193326Sed///           'unsigned'
628193326Sed///           'float'
629193326Sed///           'double'
630193326Sed///           'void'
631193326Sed/// [GNU]     typeof-specifier
632193326Sed/// [GNU]     '_Complex'
633193326Sed/// [C++0x]   'auto'                                                [TODO]
634195099Sed/// [C++0x]   'decltype' ( expression )
635193326Sed///
636193326Sed///         type-name:
637193326Sed///           class-name
638193326Sed///           enum-name
639193326Sed///           typedef-name
640193326Sed///
641193326Sed///         elaborated-type-specifier:
642193326Sed///           class-key '::'[opt] nested-name-specifier[opt] identifier
643193326Sed///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
644193326Sed///               simple-template-id
645193326Sed///           'enum' '::'[opt] nested-name-specifier[opt] identifier
646193326Sed///
647193326Sed///         enum-name:
648193326Sed///           identifier
649193326Sed///
650193326Sed///         enum-specifier:
651193326Sed///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
652193326Sed///           'enum' identifier[opt] '{' enumerator-list ',' '}'
653193326Sed///
654193326Sed///         class-specifier:
655193326Sed///           class-head '{' member-specification[opt] '}'
656193326Sed///
657193326Sed///         class-head:
658193326Sed///           class-key identifier[opt] base-clause[opt]
659193326Sed///           class-key nested-name-specifier identifier base-clause[opt]
660193326Sed///           class-key nested-name-specifier[opt] simple-template-id
661193326Sed///               base-clause[opt]
662193326Sed///
663193326Sed///         class-key:
664193326Sed///           'class'
665193326Sed///           'struct'
666193326Sed///           'union'
667193326Sed///
668193326Sed///         cv-qualifier:
669193326Sed///           'const'
670193326Sed///           'volatile'
671193326Sed/// [GNU]     restrict
672193326Sed///
673193326SedParser::TPResult Parser::isCXXDeclarationSpecifier() {
674193326Sed  switch (Tok.getKind()) {
675193326Sed  case tok::identifier:   // foo::bar
676203955Srdivacky    // Check for need to substitute AltiVec __vector keyword
677203955Srdivacky    // for "vector" identifier.
678203955Srdivacky    if (TryAltiVecVectorToken())
679203955Srdivacky      return TPResult::True();
680203955Srdivacky    // Fall through.
681193326Sed  case tok::kw_typename:  // typename T::type
682193326Sed    // Annotate typenames and C++ scope specifiers.  If we get one, just
683193326Sed    // recurse to handle whatever we get.
684193326Sed    if (TryAnnotateTypeOrScopeToken())
685204643Srdivacky      return TPResult::Error();
686204643Srdivacky    if (Tok.is(tok::identifier))
687204643Srdivacky      return TPResult::False();
688204643Srdivacky    return isCXXDeclarationSpecifier();
689193326Sed
690201361Srdivacky  case tok::coloncolon: {    // ::foo::bar
691201361Srdivacky    const Token &Next = NextToken();
692201361Srdivacky    if (Next.is(tok::kw_new) ||    // ::new
693201361Srdivacky        Next.is(tok::kw_delete))   // ::delete
694201361Srdivacky      return TPResult::False();
695198092Srdivacky
696193326Sed    // Annotate typenames and C++ scope specifiers.  If we get one, just
697193326Sed    // recurse to handle whatever we get.
698193326Sed    if (TryAnnotateTypeOrScopeToken())
699204643Srdivacky      return TPResult::Error();
700204643Srdivacky    return isCXXDeclarationSpecifier();
701201361Srdivacky  }
702201361Srdivacky
703193326Sed    // decl-specifier:
704193326Sed    //   storage-class-specifier
705193326Sed    //   type-specifier
706193326Sed    //   function-specifier
707193326Sed    //   'friend'
708193326Sed    //   'typedef'
709198954Srdivacky    //   'constexpr'
710193326Sed  case tok::kw_friend:
711193326Sed  case tok::kw_typedef:
712198954Srdivacky  case tok::kw_constexpr:
713193326Sed    // storage-class-specifier
714193326Sed  case tok::kw_register:
715193326Sed  case tok::kw_static:
716193326Sed  case tok::kw_extern:
717193326Sed  case tok::kw_mutable:
718193326Sed  case tok::kw_auto:
719193326Sed  case tok::kw___thread:
720193326Sed    // function-specifier
721193326Sed  case tok::kw_inline:
722193326Sed  case tok::kw_virtual:
723193326Sed  case tok::kw_explicit:
724193326Sed
725193326Sed    // type-specifier:
726193326Sed    //   simple-type-specifier
727193326Sed    //   class-specifier
728193326Sed    //   enum-specifier
729193326Sed    //   elaborated-type-specifier
730193326Sed    //   typename-specifier
731193326Sed    //   cv-qualifier
732193326Sed
733193326Sed    // class-specifier
734193326Sed    // elaborated-type-specifier
735193326Sed  case tok::kw_class:
736193326Sed  case tok::kw_struct:
737193326Sed  case tok::kw_union:
738193326Sed    // enum-specifier
739193326Sed  case tok::kw_enum:
740193326Sed    // cv-qualifier
741193326Sed  case tok::kw_const:
742193326Sed  case tok::kw_volatile:
743193326Sed
744193326Sed    // GNU
745193326Sed  case tok::kw_restrict:
746193326Sed  case tok::kw__Complex:
747193326Sed  case tok::kw___attribute:
748193326Sed    return TPResult::True();
749198092Srdivacky
750193326Sed    // Microsoft
751193326Sed  case tok::kw___declspec:
752193326Sed  case tok::kw___cdecl:
753193326Sed  case tok::kw___stdcall:
754193326Sed  case tok::kw___fastcall:
755208600Srdivacky  case tok::kw___thiscall:
756194179Sed  case tok::kw___w64:
757194179Sed  case tok::kw___ptr64:
758194179Sed  case tok::kw___forceinline:
759194179Sed    return TPResult::True();
760212904Sdim
761212904Sdim    // Borland
762212904Sdim  case tok::kw___pascal:
763212904Sdim    return TPResult::True();
764203955Srdivacky
765203955Srdivacky    // AltiVec
766203955Srdivacky  case tok::kw___vector:
767203955Srdivacky    return TPResult::True();
768193326Sed
769207619Srdivacky  case tok::annot_template_id: {
770207619Srdivacky    TemplateIdAnnotation *TemplateId
771207619Srdivacky      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
772207619Srdivacky    if (TemplateId->Kind != TNK_Type_template)
773207619Srdivacky      return TPResult::False();
774207619Srdivacky    CXXScopeSpec SS;
775207619Srdivacky    AnnotateTemplateIdTokenAsType(&SS);
776207619Srdivacky    assert(Tok.is(tok::annot_typename));
777207619Srdivacky    goto case_typename;
778207619Srdivacky  }
779207619Srdivacky
780201361Srdivacky  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
781201361Srdivacky    // We've already annotated a scope; try to annotate a type.
782204643Srdivacky    if (TryAnnotateTypeOrScopeToken())
783204643Srdivacky      return TPResult::Error();
784204643Srdivacky    if (!Tok.is(tok::annot_typename))
785201361Srdivacky      return TPResult::False();
786201361Srdivacky    // If that succeeded, fallthrough into the generic simple-type-id case.
787201361Srdivacky
788193326Sed    // The ambiguity resides in a simple-type-specifier/typename-specifier
789193326Sed    // followed by a '('. The '(' could either be the start of:
790193326Sed    //
791193326Sed    //   direct-declarator:
792193326Sed    //     '(' declarator ')'
793193326Sed    //
794193326Sed    //   direct-abstract-declarator:
795193326Sed    //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
796193326Sed    //              exception-specification[opt]
797193326Sed    //     '(' abstract-declarator ')'
798193326Sed    //
799193326Sed    // or part of a function-style cast expression:
800193326Sed    //
801193326Sed    //     simple-type-specifier '(' expression-list[opt] ')'
802193326Sed    //
803193326Sed
804193326Sed    // simple-type-specifier:
805193326Sed
806193326Sed  case tok::kw_char:
807193326Sed  case tok::kw_wchar_t:
808198092Srdivacky  case tok::kw_char16_t:
809198092Srdivacky  case tok::kw_char32_t:
810193326Sed  case tok::kw_bool:
811193326Sed  case tok::kw_short:
812193326Sed  case tok::kw_int:
813193326Sed  case tok::kw_long:
814193326Sed  case tok::kw_signed:
815193326Sed  case tok::kw_unsigned:
816193326Sed  case tok::kw_float:
817193326Sed  case tok::kw_double:
818193326Sed  case tok::kw_void:
819193326Sed  case tok::annot_typename:
820207619Srdivacky  case_typename:
821193326Sed    if (NextToken().is(tok::l_paren))
822193326Sed      return TPResult::Ambiguous();
823193326Sed
824193326Sed    return TPResult::True();
825193326Sed
826195099Sed  // GNU typeof support.
827193326Sed  case tok::kw_typeof: {
828193326Sed    if (NextToken().isNot(tok::l_paren))
829193326Sed      return TPResult::True();
830193326Sed
831193326Sed    TentativeParsingAction PA(*this);
832193326Sed
833193326Sed    TPResult TPR = TryParseTypeofSpecifier();
834193326Sed    bool isFollowedByParen = Tok.is(tok::l_paren);
835193326Sed
836193326Sed    PA.Revert();
837193326Sed
838193326Sed    if (TPR == TPResult::Error())
839193326Sed      return TPResult::Error();
840193326Sed
841193326Sed    if (isFollowedByParen)
842193326Sed      return TPResult::Ambiguous();
843193326Sed
844193326Sed    return TPResult::True();
845193326Sed  }
846193326Sed
847195099Sed  // C++0x decltype support.
848195099Sed  case tok::kw_decltype:
849195099Sed    return TPResult::True();
850195099Sed
851193326Sed  default:
852193326Sed    return TPResult::False();
853193326Sed  }
854193326Sed}
855193326Sed
856193326Sed/// [GNU] typeof-specifier:
857193326Sed///         'typeof' '(' expressions ')'
858193326Sed///         'typeof' '(' type-name ')'
859193326Sed///
860193326SedParser::TPResult Parser::TryParseTypeofSpecifier() {
861193326Sed  assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
862193326Sed  ConsumeToken();
863193326Sed
864193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
865193326Sed  // Parse through the parens after 'typeof'.
866193326Sed  ConsumeParen();
867193326Sed  if (!SkipUntil(tok::r_paren))
868193326Sed    return TPResult::Error();
869193326Sed
870193326Sed  return TPResult::Ambiguous();
871193326Sed}
872193326Sed
873193326SedParser::TPResult Parser::TryParseDeclarationSpecifier() {
874193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
875193326Sed  if (TPR != TPResult::Ambiguous())
876193326Sed    return TPR;
877193326Sed
878193326Sed  if (Tok.is(tok::kw_typeof))
879193326Sed    TryParseTypeofSpecifier();
880193326Sed  else
881193326Sed    ConsumeToken();
882198092Srdivacky
883193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('!");
884193326Sed  return TPResult::Ambiguous();
885193326Sed}
886193326Sed
887193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
888193326Sed/// a constructor-style initializer, when parsing declaration statements.
889193326Sed/// Returns true for function declarator and false for constructor-style
890193326Sed/// initializer.
891193326Sed/// If during the disambiguation process a parsing error is encountered,
892193326Sed/// the function returns true to let the declaration parsing code handle it.
893193326Sed///
894193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
895193326Sed///         exception-specification[opt]
896193326Sed///
897193326Sedbool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) {
898193326Sed
899193326Sed  // C++ 8.2p1:
900193326Sed  // The ambiguity arising from the similarity between a function-style cast and
901193326Sed  // a declaration mentioned in 6.8 can also occur in the context of a
902193326Sed  // declaration. In that context, the choice is between a function declaration
903193326Sed  // with a redundant set of parentheses around a parameter name and an object
904193326Sed  // declaration with a function-style cast as the initializer. Just as for the
905193326Sed  // ambiguities mentioned in 6.8, the resolution is to consider any construct
906193326Sed  // that could possibly be a declaration a declaration.
907193326Sed
908193326Sed  TentativeParsingAction PA(*this);
909193326Sed
910193326Sed  ConsumeParen();
911193326Sed  TPResult TPR = TryParseParameterDeclarationClause();
912193326Sed  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
913193326Sed    TPR = TPResult::False();
914193326Sed
915193326Sed  SourceLocation TPLoc = Tok.getLocation();
916193326Sed  PA.Revert();
917193326Sed
918193326Sed  // In case of an error, let the declaration parsing code handle it.
919193326Sed  if (TPR == TPResult::Error())
920193326Sed    return true;
921193326Sed
922193326Sed  if (TPR == TPResult::Ambiguous()) {
923193326Sed    // Function declarator has precedence over constructor-style initializer.
924193326Sed    // Emit a warning just in case the author intended a variable definition.
925193326Sed    if (warnIfAmbiguous)
926193326Sed      Diag(Tok, diag::warn_parens_disambiguated_as_function_decl)
927193326Sed        << SourceRange(Tok.getLocation(), TPLoc);
928193326Sed    return true;
929193326Sed  }
930193326Sed
931193326Sed  return TPR == TPResult::True();
932193326Sed}
933193326Sed
934193326Sed/// parameter-declaration-clause:
935193326Sed///   parameter-declaration-list[opt] '...'[opt]
936193326Sed///   parameter-declaration-list ',' '...'
937193326Sed///
938193326Sed/// parameter-declaration-list:
939193326Sed///   parameter-declaration
940193326Sed///   parameter-declaration-list ',' parameter-declaration
941193326Sed///
942193326Sed/// parameter-declaration:
943193326Sed///   decl-specifier-seq declarator
944193326Sed///   decl-specifier-seq declarator '=' assignment-expression
945193326Sed///   decl-specifier-seq abstract-declarator[opt]
946193326Sed///   decl-specifier-seq abstract-declarator[opt] '=' assignment-expression
947193326Sed///
948193326SedParser::TPResult Parser::TryParseParameterDeclarationClause() {
949193326Sed
950193326Sed  if (Tok.is(tok::r_paren))
951193326Sed    return TPResult::True();
952193326Sed
953193326Sed  //   parameter-declaration-list[opt] '...'[opt]
954193326Sed  //   parameter-declaration-list ',' '...'
955193326Sed  //
956193326Sed  // parameter-declaration-list:
957193326Sed  //   parameter-declaration
958193326Sed  //   parameter-declaration-list ',' parameter-declaration
959193326Sed  //
960193326Sed  while (1) {
961193326Sed    // '...'[opt]
962193326Sed    if (Tok.is(tok::ellipsis)) {
963193326Sed      ConsumeToken();
964193326Sed      return TPResult::True(); // '...' is a sign of a function declarator.
965193326Sed    }
966193326Sed
967193326Sed    // decl-specifier-seq
968193326Sed    TPResult TPR = TryParseDeclarationSpecifier();
969193326Sed    if (TPR != TPResult::Ambiguous())
970193326Sed      return TPR;
971193326Sed
972193326Sed    // declarator
973193326Sed    // abstract-declarator[opt]
974193326Sed    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
975193326Sed    if (TPR != TPResult::Ambiguous())
976193326Sed      return TPR;
977193326Sed
978193326Sed    if (Tok.is(tok::equal)) {
979193326Sed      // '=' assignment-expression
980193326Sed      // Parse through assignment-expression.
981193326Sed      tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren };
982193326Sed      if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/))
983193326Sed        return TPResult::Error();
984193326Sed    }
985193326Sed
986193326Sed    if (Tok.is(tok::ellipsis)) {
987193326Sed      ConsumeToken();
988193326Sed      return TPResult::True(); // '...' is a sign of a function declarator.
989193326Sed    }
990193326Sed
991193326Sed    if (Tok.isNot(tok::comma))
992193326Sed      break;
993193326Sed    ConsumeToken(); // the comma.
994193326Sed  }
995193326Sed
996193326Sed  return TPResult::Ambiguous();
997193326Sed}
998193326Sed
999193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
1000193326Sed/// parsing as a function declarator.
1001193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
1002193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or
1003193326Sed/// Error().
1004198092Srdivacky///
1005193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1006193326Sed///         exception-specification[opt]
1007193326Sed///
1008193326Sed/// exception-specification:
1009193326Sed///   'throw' '(' type-id-list[opt] ')'
1010193326Sed///
1011193326SedParser::TPResult Parser::TryParseFunctionDeclarator() {
1012193326Sed
1013193326Sed  // The '(' is already parsed.
1014193326Sed
1015193326Sed  TPResult TPR = TryParseParameterDeclarationClause();
1016193326Sed  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
1017193326Sed    TPR = TPResult::False();
1018193326Sed
1019193326Sed  if (TPR == TPResult::False() || TPR == TPResult::Error())
1020193326Sed    return TPR;
1021193326Sed
1022193326Sed  // Parse through the parens.
1023193326Sed  if (!SkipUntil(tok::r_paren))
1024193326Sed    return TPResult::Error();
1025193326Sed
1026193326Sed  // cv-qualifier-seq
1027193326Sed  while (Tok.is(tok::kw_const)    ||
1028193326Sed         Tok.is(tok::kw_volatile) ||
1029193326Sed         Tok.is(tok::kw_restrict)   )
1030193326Sed    ConsumeToken();
1031193326Sed
1032193326Sed  // exception-specification
1033193326Sed  if (Tok.is(tok::kw_throw)) {
1034193326Sed    ConsumeToken();
1035193326Sed    if (Tok.isNot(tok::l_paren))
1036193326Sed      return TPResult::Error();
1037193326Sed
1038193326Sed    // Parse through the parens after 'throw'.
1039193326Sed    ConsumeParen();
1040193326Sed    if (!SkipUntil(tok::r_paren))
1041193326Sed      return TPResult::Error();
1042193326Sed  }
1043193326Sed
1044193326Sed  return TPResult::Ambiguous();
1045193326Sed}
1046193326Sed
1047193326Sed/// '[' constant-expression[opt] ']'
1048193326Sed///
1049193326SedParser::TPResult Parser::TryParseBracketDeclarator() {
1050193326Sed  ConsumeBracket();
1051193326Sed  if (!SkipUntil(tok::r_square))
1052193326Sed    return TPResult::Error();
1053193326Sed
1054193326Sed  return TPResult::Ambiguous();
1055193326Sed}
1056