ParseTentative.cpp revision 221345
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:
61221345Sdim  case tok::kw__Static_assert:
62193326Sed    return true;
63199990Srdivacky    // simple-declaration
64193326Sed  default:
65193326Sed    return isCXXSimpleDeclaration();
66193326Sed  }
67193326Sed}
68193326Sed
69193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates
70193326Sed/// between a simple-declaration or an expression-statement.
71193326Sed/// If during the disambiguation process a parsing error is encountered,
72193326Sed/// the function returns true to let the declaration parsing code handle it.
73193326Sed/// Returns false if the statement is disambiguated as expression.
74193326Sed///
75193326Sed/// simple-declaration:
76193326Sed///   decl-specifier-seq init-declarator-list[opt] ';'
77193326Sed///
78193326Sedbool Parser::isCXXSimpleDeclaration() {
79193326Sed  // C++ 6.8p1:
80193326Sed  // There is an ambiguity in the grammar involving expression-statements and
81193326Sed  // declarations: An expression-statement with a function-style explicit type
82193326Sed  // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
83193326Sed  // from a declaration where the first declarator starts with a '('. In those
84193326Sed  // cases the statement is a declaration. [Note: To disambiguate, the whole
85193326Sed  // statement might have to be examined to determine if it is an
86193326Sed  // expression-statement or a declaration].
87193326Sed
88193326Sed  // C++ 6.8p3:
89193326Sed  // The disambiguation is purely syntactic; that is, the meaning of the names
90193326Sed  // occurring in such a statement, beyond whether they are type-names or not,
91193326Sed  // is not generally used in or changed by the disambiguation. Class
92193326Sed  // templates are instantiated as necessary to determine if a qualified name
93193326Sed  // is a type-name. Disambiguation precedes parsing, and a statement
94193326Sed  // disambiguated as a declaration may be an ill-formed declaration.
95193326Sed
96193326Sed  // We don't have to parse all of the decl-specifier-seq part. There's only
97193326Sed  // an ambiguity if the first decl-specifier is
98193326Sed  // simple-type-specifier/typename-specifier followed by a '(', which may
99193326Sed  // indicate a function-style cast expression.
100193326Sed  // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
101193326Sed  // a case.
102193326Sed
103193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
104193326Sed  if (TPR != TPResult::Ambiguous())
105193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
106193326Sed                                     // TPResult::Error().
107193326Sed
108193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
109193326Sed  // and how they were resolved (number of declarations+number of expressions).
110193326Sed
111193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
112193326Sed  // We need tentative parsing...
113193326Sed
114193326Sed  TentativeParsingAction PA(*this);
115193326Sed  TPR = TryParseSimpleDeclaration();
116193326Sed  PA.Revert();
117193326Sed
118193326Sed  // In case of an error, let the declaration parsing code handle it.
119193326Sed  if (TPR == TPResult::Error())
120193326Sed    return true;
121193326Sed
122193326Sed  // Declarations take precedence over expressions.
123193326Sed  if (TPR == TPResult::Ambiguous())
124193326Sed    TPR = TPResult::True();
125193326Sed
126193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
127193326Sed  return TPR == TPResult::True();
128193326Sed}
129193326Sed
130193326Sed/// simple-declaration:
131193326Sed///   decl-specifier-seq init-declarator-list[opt] ';'
132193326Sed///
133193326SedParser::TPResult Parser::TryParseSimpleDeclaration() {
134193326Sed  // We know that we have a simple-type-specifier/typename-specifier followed
135193326Sed  // by a '('.
136193326Sed  assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
137193326Sed
138193326Sed  if (Tok.is(tok::kw_typeof))
139193326Sed    TryParseTypeofSpecifier();
140218893Sdim  else {
141193326Sed    ConsumeToken();
142218893Sdim
143218893Sdim    if (getLang().ObjC1 && Tok.is(tok::less))
144218893Sdim      TryParseProtocolQualifiers();
145218893Sdim  }
146218893Sdim
147193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
148193326Sed
149193326Sed  TPResult TPR = TryParseInitDeclaratorList();
150193326Sed  if (TPR != TPResult::Ambiguous())
151193326Sed    return TPR;
152193326Sed
153193326Sed  if (Tok.isNot(tok::semi))
154193326Sed    return TPResult::False();
155193326Sed
156193326Sed  return TPResult::Ambiguous();
157193326Sed}
158193326Sed
159193326Sed///       init-declarator-list:
160193326Sed///         init-declarator
161193326Sed///         init-declarator-list ',' init-declarator
162193326Sed///
163193326Sed///       init-declarator:
164193326Sed///         declarator initializer[opt]
165193326Sed/// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
166193326Sed///
167193326Sed/// initializer:
168193326Sed///   '=' initializer-clause
169193326Sed///   '(' expression-list ')'
170193326Sed///
171193326Sed/// initializer-clause:
172193326Sed///   assignment-expression
173193326Sed///   '{' initializer-list ','[opt] '}'
174193326Sed///   '{' '}'
175193326Sed///
176193326SedParser::TPResult Parser::TryParseInitDeclaratorList() {
177193326Sed  while (1) {
178193326Sed    // declarator
179193326Sed    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
180193326Sed    if (TPR != TPResult::Ambiguous())
181193326Sed      return TPR;
182193326Sed
183193326Sed    // [GNU] simple-asm-expr[opt] attributes[opt]
184193326Sed    if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
185193326Sed      return TPResult::True();
186193326Sed
187193326Sed    // initializer[opt]
188193326Sed    if (Tok.is(tok::l_paren)) {
189193326Sed      // Parse through the parens.
190193326Sed      ConsumeParen();
191193326Sed      if (!SkipUntil(tok::r_paren))
192193326Sed        return TPResult::Error();
193212904Sdim    } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
194212904Sdim      // MSVC and g++ won't examine the rest of declarators if '=' is
195212904Sdim      // encountered; they just conclude that we have a declaration.
196212904Sdim      // EDG parses the initializer completely, which is the proper behavior
197212904Sdim      // for this case.
198193326Sed      //
199212904Sdim      // At present, Clang follows MSVC and g++, since the parser does not have
200212904Sdim      // the ability to parse an expression fully without recording the
201212904Sdim      // results of that parse.
202212904Sdim      // Also allow 'in' after on objective-c declaration as in:
203212904Sdim      // for (int (^b)(void) in array). Ideally this should be done in the
204212904Sdim      // context of parsing for-init-statement of a foreach statement only. But,
205212904Sdim      // in any other context 'in' is invalid after a declaration and parser
206212904Sdim      // issues the error regardless of outcome of this decision.
207212904Sdim      // FIXME. Change if above assumption does not hold.
208212904Sdim      return TPResult::True();
209193326Sed    }
210193326Sed
211193326Sed    if (Tok.isNot(tok::comma))
212193326Sed      break;
213193326Sed    ConsumeToken(); // the comma.
214193326Sed  }
215193326Sed
216193326Sed  return TPResult::Ambiguous();
217193326Sed}
218193326Sed
219193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an
220193326Sed/// expression for a condition of a if/switch/while/for statement.
221193326Sed/// If during the disambiguation process a parsing error is encountered,
222193326Sed/// the function returns true to let the declaration parsing code handle it.
223193326Sed///
224193326Sed///       condition:
225193326Sed///         expression
226193326Sed///         type-specifier-seq declarator '=' assignment-expression
227193326Sed/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
228193326Sed///             '=' assignment-expression
229193326Sed///
230193326Sedbool Parser::isCXXConditionDeclaration() {
231193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
232193326Sed  if (TPR != TPResult::Ambiguous())
233193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
234193326Sed                                     // TPResult::Error().
235193326Sed
236193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
237193326Sed  // and how they were resolved (number of declarations+number of expressions).
238193326Sed
239193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
240193326Sed  // We need tentative parsing...
241193326Sed
242193326Sed  TentativeParsingAction PA(*this);
243193326Sed
244193326Sed  // type-specifier-seq
245193326Sed  if (Tok.is(tok::kw_typeof))
246193326Sed    TryParseTypeofSpecifier();
247218893Sdim  else {
248193326Sed    ConsumeToken();
249218893Sdim
250218893Sdim    if (getLang().ObjC1 && Tok.is(tok::less))
251218893Sdim      TryParseProtocolQualifiers();
252218893Sdim  }
253193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
254193326Sed
255193326Sed  // declarator
256193326Sed  TPR = TryParseDeclarator(false/*mayBeAbstract*/);
257193326Sed
258193326Sed  // In case of an error, let the declaration parsing code handle it.
259193326Sed  if (TPR == TPResult::Error())
260193326Sed    TPR = TPResult::True();
261193326Sed
262193326Sed  if (TPR == TPResult::Ambiguous()) {
263193326Sed    // '='
264193326Sed    // [GNU] simple-asm-expr[opt] attributes[opt]
265193326Sed    if (Tok.is(tok::equal)  ||
266193326Sed        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
267193326Sed      TPR = TPResult::True();
268193326Sed    else
269193326Sed      TPR = TPResult::False();
270193326Sed  }
271193326Sed
272193326Sed  PA.Revert();
273193326Sed
274193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
275193326Sed  return TPR == TPResult::True();
276193326Sed}
277193326Sed
278198092Srdivacky  /// \brief Determine whether the next set of tokens contains a type-id.
279193326Sed  ///
280193326Sed  /// The context parameter states what context we're parsing right
281193326Sed  /// now, which affects how this routine copes with the token
282193326Sed  /// following the type-id. If the context is TypeIdInParens, we have
283193326Sed  /// already parsed the '(' and we will cease lookahead when we hit
284193326Sed  /// the corresponding ')'. If the context is
285193326Sed  /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
286193326Sed  /// before this template argument, and will cease lookahead when we
287193326Sed  /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
288193326Sed  /// and false for an expression.  If during the disambiguation
289193326Sed  /// process a parsing error is encountered, the function returns
290193326Sed  /// true to let the declaration parsing code handle it.
291193326Sed  ///
292193326Sed  /// type-id:
293193326Sed  ///   type-specifier-seq abstract-declarator[opt]
294193326Sed  ///
295193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
296198092Srdivacky
297193326Sed  isAmbiguous = false;
298193326Sed
299193326Sed  // C++ 8.2p2:
300193326Sed  // The ambiguity arising from the similarity between a function-style cast and
301193326Sed  // a type-id can occur in different contexts. The ambiguity appears as a
302193326Sed  // choice between a function-style cast expression and a declaration of a
303193326Sed  // type. The resolution is that any construct that could possibly be a type-id
304193326Sed  // in its syntactic context shall be considered a type-id.
305193326Sed
306193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
307193326Sed  if (TPR != TPResult::Ambiguous())
308193326Sed    return TPR != TPResult::False(); // Returns true for TPResult::True() or
309193326Sed                                     // TPResult::Error().
310193326Sed
311193326Sed  // FIXME: Add statistics about the number of ambiguous statements encountered
312193326Sed  // and how they were resolved (number of declarations+number of expressions).
313193326Sed
314193326Sed  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
315193326Sed  // We need tentative parsing...
316193326Sed
317193326Sed  TentativeParsingAction PA(*this);
318193326Sed
319193326Sed  // type-specifier-seq
320193326Sed  if (Tok.is(tok::kw_typeof))
321193326Sed    TryParseTypeofSpecifier();
322218893Sdim  else {
323193326Sed    ConsumeToken();
324218893Sdim
325218893Sdim    if (getLang().ObjC1 && Tok.is(tok::less))
326218893Sdim      TryParseProtocolQualifiers();
327218893Sdim  }
328218893Sdim
329193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
330193326Sed
331193326Sed  // declarator
332193326Sed  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
333193326Sed
334193326Sed  // In case of an error, let the declaration parsing code handle it.
335193326Sed  if (TPR == TPResult::Error())
336193326Sed    TPR = TPResult::True();
337193326Sed
338193326Sed  if (TPR == TPResult::Ambiguous()) {
339193326Sed    // We are supposed to be inside parens, so if after the abstract declarator
340193326Sed    // we encounter a ')' this is a type-id, otherwise it's an expression.
341193326Sed    if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
342193326Sed      TPR = TPResult::True();
343193326Sed      isAmbiguous = true;
344193326Sed
345193326Sed    // We are supposed to be inside a template argument, so if after
346193326Sed    // the abstract declarator we encounter a '>', '>>' (in C++0x), or
347193326Sed    // ',', this is a type-id. Otherwise, it's an expression.
348193326Sed    } else if (Context == TypeIdAsTemplateArgument &&
349193326Sed               (Tok.is(tok::greater) || Tok.is(tok::comma) ||
350193326Sed                (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
351193326Sed      TPR = TPResult::True();
352193326Sed      isAmbiguous = true;
353193326Sed
354193326Sed    } else
355193326Sed      TPR = TPResult::False();
356193326Sed  }
357193326Sed
358193326Sed  PA.Revert();
359193326Sed
360193326Sed  assert(TPR == TPResult::True() || TPR == TPResult::False());
361193326Sed  return TPR == TPResult::True();
362193326Sed}
363193326Sed
364199990Srdivacky/// isCXX0XAttributeSpecifier - returns true if this is a C++0x
365199990Srdivacky/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
366199990Srdivacky/// performed that will simply return true if a [[ is seen. Currently C++ has no
367199990Srdivacky/// syntactical ambiguities from this check, but it may inhibit error recovery.
368199990Srdivacky/// If CheckClosing is true, a check is made for closing ]] brackets.
369199990Srdivacky///
370199990Srdivacky/// If given, After is set to the token after the attribute-specifier so that
371199990Srdivacky/// appropriate parsing decisions can be made; it is left untouched if false is
372199990Srdivacky/// returned.
373199990Srdivacky///
374199990Srdivacky/// FIXME: If an error is in the closing ]] brackets, the program assumes
375199990Srdivacky/// the absence of an attribute-specifier, which can cause very yucky errors
376199990Srdivacky/// to occur.
377199990Srdivacky///
378199990Srdivacky/// [C++0x] attribute-specifier:
379199990Srdivacky///         '[' '[' attribute-list ']' ']'
380199990Srdivacky///
381199990Srdivacky/// [C++0x] attribute-list:
382199990Srdivacky///         attribute[opt]
383199990Srdivacky///         attribute-list ',' attribute[opt]
384199990Srdivacky///
385199990Srdivacky/// [C++0x] attribute:
386199990Srdivacky///         attribute-token attribute-argument-clause[opt]
387199990Srdivacky///
388199990Srdivacky/// [C++0x] attribute-token:
389199990Srdivacky///         identifier
390199990Srdivacky///         attribute-scoped-token
391199990Srdivacky///
392199990Srdivacky/// [C++0x] attribute-scoped-token:
393199990Srdivacky///         attribute-namespace '::' identifier
394199990Srdivacky///
395199990Srdivacky/// [C++0x] attribute-namespace:
396199990Srdivacky///         identifier
397199990Srdivacky///
398199990Srdivacky/// [C++0x] attribute-argument-clause:
399199990Srdivacky///         '(' balanced-token-seq ')'
400199990Srdivacky///
401199990Srdivacky/// [C++0x] balanced-token-seq:
402199990Srdivacky///         balanced-token
403199990Srdivacky///         balanced-token-seq balanced-token
404199990Srdivacky///
405199990Srdivacky/// [C++0x] balanced-token:
406199990Srdivacky///         '(' balanced-token-seq ')'
407199990Srdivacky///         '[' balanced-token-seq ']'
408199990Srdivacky///         '{' balanced-token-seq '}'
409199990Srdivacky///         any token but '(', ')', '[', ']', '{', or '}'
410199990Srdivackybool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
411199990Srdivacky                                        tok::TokenKind *After) {
412199990Srdivacky  if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
413199990Srdivacky    return false;
414199990Srdivacky
415199990Srdivacky  // No tentative parsing if we don't need to look for ]]
416199990Srdivacky  if (!CheckClosing && !getLang().ObjC1)
417199990Srdivacky    return true;
418199990Srdivacky
419199990Srdivacky  struct TentativeReverter {
420199990Srdivacky    TentativeParsingAction PA;
421199990Srdivacky
422199990Srdivacky    TentativeReverter (Parser& P)
423199990Srdivacky      : PA(P)
424199990Srdivacky    {}
425199990Srdivacky    ~TentativeReverter () {
426199990Srdivacky      PA.Revert();
427199990Srdivacky    }
428199990Srdivacky  } R(*this);
429199990Srdivacky
430199990Srdivacky  // Opening brackets were checked for above.
431199990Srdivacky  ConsumeBracket();
432199990Srdivacky  ConsumeBracket();
433199990Srdivacky
434199990Srdivacky  // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
435199990Srdivacky  SkipUntil(tok::r_square, false);
436199990Srdivacky
437199990Srdivacky  if (Tok.isNot(tok::r_square))
438199990Srdivacky    return false;
439199990Srdivacky  ConsumeBracket();
440199990Srdivacky
441199990Srdivacky  if (After)
442199990Srdivacky    *After = Tok.getKind();
443199990Srdivacky
444199990Srdivacky  return true;
445199990Srdivacky}
446199990Srdivacky
447193326Sed///         declarator:
448193326Sed///           direct-declarator
449193326Sed///           ptr-operator declarator
450193326Sed///
451193326Sed///         direct-declarator:
452193326Sed///           declarator-id
453193326Sed///           direct-declarator '(' parameter-declaration-clause ')'
454193326Sed///                 cv-qualifier-seq[opt] exception-specification[opt]
455193326Sed///           direct-declarator '[' constant-expression[opt] ']'
456193326Sed///           '(' declarator ')'
457193326Sed/// [GNU]     '(' attributes declarator ')'
458193326Sed///
459193326Sed///         abstract-declarator:
460193326Sed///           ptr-operator abstract-declarator[opt]
461193326Sed///           direct-abstract-declarator
462218893Sdim///           ...
463193326Sed///
464193326Sed///         direct-abstract-declarator:
465193326Sed///           direct-abstract-declarator[opt]
466193326Sed///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
467193326Sed///                 exception-specification[opt]
468193326Sed///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
469193326Sed///           '(' abstract-declarator ')'
470193326Sed///
471193326Sed///         ptr-operator:
472193326Sed///           '*' cv-qualifier-seq[opt]
473193326Sed///           '&'
474193326Sed/// [C++0x]   '&&'                                                        [TODO]
475193326Sed///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
476193326Sed///
477193326Sed///         cv-qualifier-seq:
478193326Sed///           cv-qualifier cv-qualifier-seq[opt]
479193326Sed///
480193326Sed///         cv-qualifier:
481193326Sed///           'const'
482193326Sed///           'volatile'
483193326Sed///
484193326Sed///         declarator-id:
485218893Sdim///           '...'[opt] id-expression
486193326Sed///
487193326Sed///         id-expression:
488193326Sed///           unqualified-id
489193326Sed///           qualified-id                                                [TODO]
490193326Sed///
491193326Sed///         unqualified-id:
492193326Sed///           identifier
493193326Sed///           operator-function-id                                        [TODO]
494193326Sed///           conversion-function-id                                      [TODO]
495193326Sed///           '~' class-name                                              [TODO]
496193326Sed///           template-id                                                 [TODO]
497193326Sed///
498193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
499193326Sed                                            bool mayHaveIdentifier) {
500193326Sed  // declarator:
501193326Sed  //   direct-declarator
502193326Sed  //   ptr-operator declarator
503193326Sed
504193326Sed  while (1) {
505193326Sed    if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
506204643Srdivacky      if (TryAnnotateCXXScopeToken(true))
507204643Srdivacky        return TPResult::Error();
508193326Sed
509193326Sed    if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
510218893Sdim        Tok.is(tok::ampamp) ||
511193326Sed        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
512193326Sed      // ptr-operator
513193326Sed      ConsumeToken();
514193326Sed      while (Tok.is(tok::kw_const)    ||
515193326Sed             Tok.is(tok::kw_volatile) ||
516193326Sed             Tok.is(tok::kw_restrict))
517193326Sed        ConsumeToken();
518193326Sed    } else {
519193326Sed      break;
520193326Sed    }
521193326Sed  }
522193326Sed
523193326Sed  // direct-declarator:
524193326Sed  // direct-abstract-declarator:
525218893Sdim  if (Tok.is(tok::ellipsis))
526218893Sdim    ConsumeToken();
527218893Sdim
528198092Srdivacky  if ((Tok.is(tok::identifier) ||
529198092Srdivacky       (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
530198092Srdivacky      mayHaveIdentifier) {
531193326Sed    // declarator-id
532198092Srdivacky    if (Tok.is(tok::annot_cxxscope))
533198092Srdivacky      ConsumeToken();
534193326Sed    ConsumeToken();
535193326Sed  } else if (Tok.is(tok::l_paren)) {
536193326Sed    ConsumeParen();
537193326Sed    if (mayBeAbstract &&
538193326Sed        (Tok.is(tok::r_paren) ||       // 'int()' is a function.
539193326Sed         Tok.is(tok::ellipsis) ||      // 'int(...)' is a function.
540193326Sed         isDeclarationSpecifier())) {   // 'int(int)' is a function.
541193326Sed      // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
542193326Sed      //        exception-specification[opt]
543193326Sed      TPResult TPR = TryParseFunctionDeclarator();
544193326Sed      if (TPR != TPResult::Ambiguous())
545193326Sed        return TPR;
546193326Sed    } else {
547193326Sed      // '(' declarator ')'
548193326Sed      // '(' attributes declarator ')'
549193326Sed      // '(' abstract-declarator ')'
550218893Sdim      if (Tok.is(tok::kw___attribute) ||
551218893Sdim          Tok.is(tok::kw___declspec) ||
552218893Sdim          Tok.is(tok::kw___cdecl) ||
553218893Sdim          Tok.is(tok::kw___stdcall) ||
554218893Sdim          Tok.is(tok::kw___fastcall) ||
555218893Sdim          Tok.is(tok::kw___thiscall))
556193326Sed        return TPResult::True(); // attributes indicate declaration
557193326Sed      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
558193326Sed      if (TPR != TPResult::Ambiguous())
559193326Sed        return TPR;
560193326Sed      if (Tok.isNot(tok::r_paren))
561193326Sed        return TPResult::False();
562193326Sed      ConsumeParen();
563193326Sed    }
564193326Sed  } else if (!mayBeAbstract) {
565193326Sed    return TPResult::False();
566193326Sed  }
567193326Sed
568193326Sed  while (1) {
569193326Sed    TPResult TPR(TPResult::Ambiguous());
570193326Sed
571218893Sdim    // abstract-declarator: ...
572218893Sdim    if (Tok.is(tok::ellipsis))
573218893Sdim      ConsumeToken();
574218893Sdim
575193326Sed    if (Tok.is(tok::l_paren)) {
576193326Sed      // Check whether we have a function declarator or a possible ctor-style
577193326Sed      // initializer that follows the declarator. Note that ctor-style
578193326Sed      // initializers are not possible in contexts where abstract declarators
579193326Sed      // are allowed.
580193326Sed      if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/))
581193326Sed        break;
582193326Sed
583193326Sed      // direct-declarator '(' parameter-declaration-clause ')'
584193326Sed      //        cv-qualifier-seq[opt] exception-specification[opt]
585193326Sed      ConsumeParen();
586193326Sed      TPR = TryParseFunctionDeclarator();
587193326Sed    } else if (Tok.is(tok::l_square)) {
588193326Sed      // direct-declarator '[' constant-expression[opt] ']'
589193326Sed      // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
590193326Sed      TPR = TryParseBracketDeclarator();
591193326Sed    } else {
592193326Sed      break;
593193326Sed    }
594193326Sed
595193326Sed    if (TPR != TPResult::Ambiguous())
596193326Sed      return TPR;
597193326Sed  }
598193326Sed
599193326Sed  return TPResult::Ambiguous();
600193326Sed}
601193326Sed
602218893SdimParser::TPResult
603218893SdimParser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
604218893Sdim  switch (Kind) {
605218893Sdim  // Obviously starts an expression.
606218893Sdim  case tok::numeric_constant:
607218893Sdim  case tok::char_constant:
608218893Sdim  case tok::string_literal:
609218893Sdim  case tok::wide_string_literal:
610218893Sdim  case tok::l_square:
611218893Sdim  case tok::l_paren:
612218893Sdim  case tok::amp:
613218893Sdim  case tok::ampamp:
614218893Sdim  case tok::star:
615218893Sdim  case tok::plus:
616218893Sdim  case tok::plusplus:
617218893Sdim  case tok::minus:
618218893Sdim  case tok::minusminus:
619218893Sdim  case tok::tilde:
620218893Sdim  case tok::exclaim:
621218893Sdim  case tok::kw_sizeof:
622218893Sdim  case tok::kw___func__:
623218893Sdim  case tok::kw_const_cast:
624218893Sdim  case tok::kw_delete:
625218893Sdim  case tok::kw_dynamic_cast:
626218893Sdim  case tok::kw_false:
627218893Sdim  case tok::kw_new:
628218893Sdim  case tok::kw_operator:
629218893Sdim  case tok::kw_reinterpret_cast:
630218893Sdim  case tok::kw_static_cast:
631218893Sdim  case tok::kw_this:
632218893Sdim  case tok::kw_throw:
633218893Sdim  case tok::kw_true:
634218893Sdim  case tok::kw_typeid:
635218893Sdim  case tok::kw_alignof:
636218893Sdim  case tok::kw_noexcept:
637218893Sdim  case tok::kw_nullptr:
638218893Sdim  case tok::kw___null:
639218893Sdim  case tok::kw___alignof:
640218893Sdim  case tok::kw___builtin_choose_expr:
641218893Sdim  case tok::kw___builtin_offsetof:
642218893Sdim  case tok::kw___builtin_types_compatible_p:
643218893Sdim  case tok::kw___builtin_va_arg:
644218893Sdim  case tok::kw___imag:
645218893Sdim  case tok::kw___real:
646218893Sdim  case tok::kw___FUNCTION__:
647218893Sdim  case tok::kw___PRETTY_FUNCTION__:
648218893Sdim  case tok::kw___has_nothrow_assign:
649218893Sdim  case tok::kw___has_nothrow_copy:
650218893Sdim  case tok::kw___has_nothrow_constructor:
651218893Sdim  case tok::kw___has_trivial_assign:
652218893Sdim  case tok::kw___has_trivial_copy:
653218893Sdim  case tok::kw___has_trivial_constructor:
654218893Sdim  case tok::kw___has_trivial_destructor:
655218893Sdim  case tok::kw___has_virtual_destructor:
656218893Sdim  case tok::kw___is_abstract:
657218893Sdim  case tok::kw___is_base_of:
658218893Sdim  case tok::kw___is_class:
659218893Sdim  case tok::kw___is_convertible_to:
660218893Sdim  case tok::kw___is_empty:
661218893Sdim  case tok::kw___is_enum:
662221345Sdim  case tok::kw___is_literal:
663221345Sdim  case tok::kw___is_literal_type:
664218893Sdim  case tok::kw___is_pod:
665218893Sdim  case tok::kw___is_polymorphic:
666221345Sdim  case tok::kw___is_trivial:
667218893Sdim  case tok::kw___is_union:
668218893Sdim  case tok::kw___uuidof:
669218893Sdim    return TPResult::True();
670218893Sdim
671218893Sdim  // Obviously starts a type-specifier-seq:
672218893Sdim  case tok::kw_char:
673218893Sdim  case tok::kw_const:
674218893Sdim  case tok::kw_double:
675218893Sdim  case tok::kw_enum:
676218893Sdim  case tok::kw_float:
677218893Sdim  case tok::kw_int:
678218893Sdim  case tok::kw_long:
679221345Sdim  case tok::kw___int64:
680218893Sdim  case tok::kw_restrict:
681218893Sdim  case tok::kw_short:
682218893Sdim  case tok::kw_signed:
683218893Sdim  case tok::kw_struct:
684218893Sdim  case tok::kw_union:
685218893Sdim  case tok::kw_unsigned:
686218893Sdim  case tok::kw_void:
687218893Sdim  case tok::kw_volatile:
688218893Sdim  case tok::kw__Bool:
689218893Sdim  case tok::kw__Complex:
690218893Sdim  case tok::kw_class:
691218893Sdim  case tok::kw_typename:
692218893Sdim  case tok::kw_wchar_t:
693218893Sdim  case tok::kw_char16_t:
694218893Sdim  case tok::kw_char32_t:
695218893Sdim  case tok::kw_decltype:
696218893Sdim  case tok::kw_thread_local:
697218893Sdim  case tok::kw__Decimal32:
698218893Sdim  case tok::kw__Decimal64:
699218893Sdim  case tok::kw__Decimal128:
700218893Sdim  case tok::kw___thread:
701218893Sdim  case tok::kw_typeof:
702218893Sdim  case tok::kw___cdecl:
703218893Sdim  case tok::kw___stdcall:
704218893Sdim  case tok::kw___fastcall:
705218893Sdim  case tok::kw___thiscall:
706218893Sdim  case tok::kw___vector:
707218893Sdim  case tok::kw___pixel:
708218893Sdim    return TPResult::False();
709218893Sdim
710218893Sdim  default:
711218893Sdim    break;
712218893Sdim  }
713218893Sdim
714218893Sdim  return TPResult::Ambiguous();
715218893Sdim}
716218893Sdim
717193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
718193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
719193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error()
720193326Sed/// if a parsing error was found and reported.
721193326Sed///
722193326Sed///         decl-specifier:
723193326Sed///           storage-class-specifier
724193326Sed///           type-specifier
725193326Sed///           function-specifier
726193326Sed///           'friend'
727193326Sed///           'typedef'
728198954Srdivacky/// [C++0x]   'constexpr'
729193326Sed/// [GNU]     attributes declaration-specifiers[opt]
730193326Sed///
731193326Sed///         storage-class-specifier:
732193326Sed///           'register'
733193326Sed///           'static'
734193326Sed///           'extern'
735193326Sed///           'mutable'
736193326Sed///           'auto'
737193326Sed/// [GNU]     '__thread'
738193326Sed///
739193326Sed///         function-specifier:
740193326Sed///           'inline'
741193326Sed///           'virtual'
742193326Sed///           'explicit'
743193326Sed///
744193326Sed///         typedef-name:
745193326Sed///           identifier
746193326Sed///
747193326Sed///         type-specifier:
748193326Sed///           simple-type-specifier
749193326Sed///           class-specifier
750193326Sed///           enum-specifier
751193326Sed///           elaborated-type-specifier
752193326Sed///           typename-specifier
753193326Sed///           cv-qualifier
754193326Sed///
755193326Sed///         simple-type-specifier:
756193326Sed///           '::'[opt] nested-name-specifier[opt] type-name
757193326Sed///           '::'[opt] nested-name-specifier 'template'
758193326Sed///                 simple-template-id                              [TODO]
759193326Sed///           'char'
760193326Sed///           'wchar_t'
761193326Sed///           'bool'
762193326Sed///           'short'
763193326Sed///           'int'
764193326Sed///           'long'
765193326Sed///           'signed'
766193326Sed///           'unsigned'
767193326Sed///           'float'
768193326Sed///           'double'
769193326Sed///           'void'
770193326Sed/// [GNU]     typeof-specifier
771193326Sed/// [GNU]     '_Complex'
772193326Sed/// [C++0x]   'auto'                                                [TODO]
773195099Sed/// [C++0x]   'decltype' ( expression )
774193326Sed///
775193326Sed///         type-name:
776193326Sed///           class-name
777193326Sed///           enum-name
778193326Sed///           typedef-name
779193326Sed///
780193326Sed///         elaborated-type-specifier:
781193326Sed///           class-key '::'[opt] nested-name-specifier[opt] identifier
782193326Sed///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
783193326Sed///               simple-template-id
784193326Sed///           'enum' '::'[opt] nested-name-specifier[opt] identifier
785193326Sed///
786193326Sed///         enum-name:
787193326Sed///           identifier
788193326Sed///
789193326Sed///         enum-specifier:
790193326Sed///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
791193326Sed///           'enum' identifier[opt] '{' enumerator-list ',' '}'
792193326Sed///
793193326Sed///         class-specifier:
794193326Sed///           class-head '{' member-specification[opt] '}'
795193326Sed///
796193326Sed///         class-head:
797193326Sed///           class-key identifier[opt] base-clause[opt]
798193326Sed///           class-key nested-name-specifier identifier base-clause[opt]
799193326Sed///           class-key nested-name-specifier[opt] simple-template-id
800193326Sed///               base-clause[opt]
801193326Sed///
802193326Sed///         class-key:
803193326Sed///           'class'
804193326Sed///           'struct'
805193326Sed///           'union'
806193326Sed///
807193326Sed///         cv-qualifier:
808193326Sed///           'const'
809193326Sed///           'volatile'
810193326Sed/// [GNU]     restrict
811193326Sed///
812193326SedParser::TPResult Parser::isCXXDeclarationSpecifier() {
813193326Sed  switch (Tok.getKind()) {
814193326Sed  case tok::identifier:   // foo::bar
815203955Srdivacky    // Check for need to substitute AltiVec __vector keyword
816203955Srdivacky    // for "vector" identifier.
817203955Srdivacky    if (TryAltiVecVectorToken())
818203955Srdivacky      return TPResult::True();
819203955Srdivacky    // Fall through.
820193326Sed  case tok::kw_typename:  // typename T::type
821193326Sed    // Annotate typenames and C++ scope specifiers.  If we get one, just
822193326Sed    // recurse to handle whatever we get.
823193326Sed    if (TryAnnotateTypeOrScopeToken())
824204643Srdivacky      return TPResult::Error();
825204643Srdivacky    if (Tok.is(tok::identifier))
826204643Srdivacky      return TPResult::False();
827204643Srdivacky    return isCXXDeclarationSpecifier();
828193326Sed
829201361Srdivacky  case tok::coloncolon: {    // ::foo::bar
830201361Srdivacky    const Token &Next = NextToken();
831201361Srdivacky    if (Next.is(tok::kw_new) ||    // ::new
832201361Srdivacky        Next.is(tok::kw_delete))   // ::delete
833201361Srdivacky      return TPResult::False();
834198092Srdivacky
835193326Sed    // Annotate typenames and C++ scope specifiers.  If we get one, just
836193326Sed    // recurse to handle whatever we get.
837193326Sed    if (TryAnnotateTypeOrScopeToken())
838204643Srdivacky      return TPResult::Error();
839204643Srdivacky    return isCXXDeclarationSpecifier();
840201361Srdivacky  }
841201361Srdivacky
842193326Sed    // decl-specifier:
843193326Sed    //   storage-class-specifier
844193326Sed    //   type-specifier
845193326Sed    //   function-specifier
846193326Sed    //   'friend'
847193326Sed    //   'typedef'
848198954Srdivacky    //   'constexpr'
849193326Sed  case tok::kw_friend:
850193326Sed  case tok::kw_typedef:
851198954Srdivacky  case tok::kw_constexpr:
852193326Sed    // storage-class-specifier
853193326Sed  case tok::kw_register:
854193326Sed  case tok::kw_static:
855193326Sed  case tok::kw_extern:
856193326Sed  case tok::kw_mutable:
857193326Sed  case tok::kw_auto:
858193326Sed  case tok::kw___thread:
859193326Sed    // function-specifier
860193326Sed  case tok::kw_inline:
861193326Sed  case tok::kw_virtual:
862193326Sed  case tok::kw_explicit:
863193326Sed
864193326Sed    // type-specifier:
865193326Sed    //   simple-type-specifier
866193326Sed    //   class-specifier
867193326Sed    //   enum-specifier
868193326Sed    //   elaborated-type-specifier
869193326Sed    //   typename-specifier
870193326Sed    //   cv-qualifier
871193326Sed
872193326Sed    // class-specifier
873193326Sed    // elaborated-type-specifier
874193326Sed  case tok::kw_class:
875193326Sed  case tok::kw_struct:
876193326Sed  case tok::kw_union:
877193326Sed    // enum-specifier
878193326Sed  case tok::kw_enum:
879193326Sed    // cv-qualifier
880193326Sed  case tok::kw_const:
881193326Sed  case tok::kw_volatile:
882193326Sed
883193326Sed    // GNU
884193326Sed  case tok::kw_restrict:
885193326Sed  case tok::kw__Complex:
886193326Sed  case tok::kw___attribute:
887193326Sed    return TPResult::True();
888198092Srdivacky
889193326Sed    // Microsoft
890193326Sed  case tok::kw___declspec:
891193326Sed  case tok::kw___cdecl:
892193326Sed  case tok::kw___stdcall:
893193326Sed  case tok::kw___fastcall:
894208600Srdivacky  case tok::kw___thiscall:
895194179Sed  case tok::kw___w64:
896194179Sed  case tok::kw___ptr64:
897194179Sed  case tok::kw___forceinline:
898194179Sed    return TPResult::True();
899212904Sdim
900212904Sdim    // Borland
901212904Sdim  case tok::kw___pascal:
902212904Sdim    return TPResult::True();
903203955Srdivacky
904203955Srdivacky    // AltiVec
905203955Srdivacky  case tok::kw___vector:
906203955Srdivacky    return TPResult::True();
907193326Sed
908207619Srdivacky  case tok::annot_template_id: {
909207619Srdivacky    TemplateIdAnnotation *TemplateId
910207619Srdivacky      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
911207619Srdivacky    if (TemplateId->Kind != TNK_Type_template)
912207619Srdivacky      return TPResult::False();
913207619Srdivacky    CXXScopeSpec SS;
914221345Sdim    AnnotateTemplateIdTokenAsType();
915207619Srdivacky    assert(Tok.is(tok::annot_typename));
916207619Srdivacky    goto case_typename;
917207619Srdivacky  }
918207619Srdivacky
919201361Srdivacky  case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
920201361Srdivacky    // We've already annotated a scope; try to annotate a type.
921204643Srdivacky    if (TryAnnotateTypeOrScopeToken())
922204643Srdivacky      return TPResult::Error();
923204643Srdivacky    if (!Tok.is(tok::annot_typename))
924201361Srdivacky      return TPResult::False();
925201361Srdivacky    // If that succeeded, fallthrough into the generic simple-type-id case.
926201361Srdivacky
927193326Sed    // The ambiguity resides in a simple-type-specifier/typename-specifier
928193326Sed    // followed by a '('. The '(' could either be the start of:
929193326Sed    //
930193326Sed    //   direct-declarator:
931193326Sed    //     '(' declarator ')'
932193326Sed    //
933193326Sed    //   direct-abstract-declarator:
934193326Sed    //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
935193326Sed    //              exception-specification[opt]
936193326Sed    //     '(' abstract-declarator ')'
937193326Sed    //
938193326Sed    // or part of a function-style cast expression:
939193326Sed    //
940193326Sed    //     simple-type-specifier '(' expression-list[opt] ')'
941193326Sed    //
942193326Sed
943193326Sed    // simple-type-specifier:
944193326Sed
945218893Sdim  case tok::annot_typename:
946218893Sdim  case_typename:
947218893Sdim    // In Objective-C, we might have a protocol-qualified type.
948218893Sdim    if (getLang().ObjC1 && NextToken().is(tok::less)) {
949218893Sdim      // Tentatively parse the
950218893Sdim      TentativeParsingAction PA(*this);
951218893Sdim      ConsumeToken(); // The type token
952218893Sdim
953218893Sdim      TPResult TPR = TryParseProtocolQualifiers();
954218893Sdim      bool isFollowedByParen = Tok.is(tok::l_paren);
955218893Sdim
956218893Sdim      PA.Revert();
957218893Sdim
958218893Sdim      if (TPR == TPResult::Error())
959218893Sdim        return TPResult::Error();
960218893Sdim
961218893Sdim      if (isFollowedByParen)
962218893Sdim        return TPResult::Ambiguous();
963218893Sdim
964218893Sdim      return TPResult::True();
965218893Sdim    }
966218893Sdim
967193326Sed  case tok::kw_char:
968193326Sed  case tok::kw_wchar_t:
969198092Srdivacky  case tok::kw_char16_t:
970198092Srdivacky  case tok::kw_char32_t:
971193326Sed  case tok::kw_bool:
972193326Sed  case tok::kw_short:
973193326Sed  case tok::kw_int:
974193326Sed  case tok::kw_long:
975221345Sdim  case tok::kw___int64:
976193326Sed  case tok::kw_signed:
977193326Sed  case tok::kw_unsigned:
978193326Sed  case tok::kw_float:
979193326Sed  case tok::kw_double:
980193326Sed  case tok::kw_void:
981193326Sed    if (NextToken().is(tok::l_paren))
982193326Sed      return TPResult::Ambiguous();
983193326Sed
984218893Sdim    if (isStartOfObjCClassMessageMissingOpenBracket())
985218893Sdim      return TPResult::False();
986218893Sdim
987193326Sed    return TPResult::True();
988193326Sed
989195099Sed  // GNU typeof support.
990193326Sed  case tok::kw_typeof: {
991193326Sed    if (NextToken().isNot(tok::l_paren))
992193326Sed      return TPResult::True();
993193326Sed
994193326Sed    TentativeParsingAction PA(*this);
995193326Sed
996193326Sed    TPResult TPR = TryParseTypeofSpecifier();
997193326Sed    bool isFollowedByParen = Tok.is(tok::l_paren);
998193326Sed
999193326Sed    PA.Revert();
1000193326Sed
1001193326Sed    if (TPR == TPResult::Error())
1002193326Sed      return TPResult::Error();
1003193326Sed
1004193326Sed    if (isFollowedByParen)
1005193326Sed      return TPResult::Ambiguous();
1006193326Sed
1007193326Sed    return TPResult::True();
1008193326Sed  }
1009193326Sed
1010195099Sed  // C++0x decltype support.
1011195099Sed  case tok::kw_decltype:
1012195099Sed    return TPResult::True();
1013195099Sed
1014193326Sed  default:
1015193326Sed    return TPResult::False();
1016193326Sed  }
1017193326Sed}
1018193326Sed
1019193326Sed/// [GNU] typeof-specifier:
1020193326Sed///         'typeof' '(' expressions ')'
1021193326Sed///         'typeof' '(' type-name ')'
1022193326Sed///
1023193326SedParser::TPResult Parser::TryParseTypeofSpecifier() {
1024193326Sed  assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
1025193326Sed  ConsumeToken();
1026193326Sed
1027193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('");
1028193326Sed  // Parse through the parens after 'typeof'.
1029193326Sed  ConsumeParen();
1030193326Sed  if (!SkipUntil(tok::r_paren))
1031193326Sed    return TPResult::Error();
1032193326Sed
1033193326Sed  return TPResult::Ambiguous();
1034193326Sed}
1035193326Sed
1036218893Sdim/// [ObjC] protocol-qualifiers:
1037218893Sdim////         '<' identifier-list '>'
1038218893SdimParser::TPResult Parser::TryParseProtocolQualifiers() {
1039218893Sdim  assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
1040218893Sdim  ConsumeToken();
1041218893Sdim  do {
1042218893Sdim    if (Tok.isNot(tok::identifier))
1043218893Sdim      return TPResult::Error();
1044218893Sdim    ConsumeToken();
1045218893Sdim
1046218893Sdim    if (Tok.is(tok::comma)) {
1047218893Sdim      ConsumeToken();
1048218893Sdim      continue;
1049218893Sdim    }
1050218893Sdim
1051218893Sdim    if (Tok.is(tok::greater)) {
1052218893Sdim      ConsumeToken();
1053218893Sdim      return TPResult::Ambiguous();
1054218893Sdim    }
1055218893Sdim  } while (false);
1056218893Sdim
1057218893Sdim  return TPResult::Error();
1058218893Sdim}
1059218893Sdim
1060193326SedParser::TPResult Parser::TryParseDeclarationSpecifier() {
1061193326Sed  TPResult TPR = isCXXDeclarationSpecifier();
1062193326Sed  if (TPR != TPResult::Ambiguous())
1063193326Sed    return TPR;
1064193326Sed
1065193326Sed  if (Tok.is(tok::kw_typeof))
1066193326Sed    TryParseTypeofSpecifier();
1067218893Sdim  else {
1068193326Sed    ConsumeToken();
1069218893Sdim
1070218893Sdim    if (getLang().ObjC1 && Tok.is(tok::less))
1071218893Sdim      TryParseProtocolQualifiers();
1072218893Sdim  }
1073198092Srdivacky
1074193326Sed  assert(Tok.is(tok::l_paren) && "Expected '('!");
1075193326Sed  return TPResult::Ambiguous();
1076193326Sed}
1077193326Sed
1078193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or
1079193326Sed/// a constructor-style initializer, when parsing declaration statements.
1080193326Sed/// Returns true for function declarator and false for constructor-style
1081193326Sed/// initializer.
1082193326Sed/// If during the disambiguation process a parsing error is encountered,
1083193326Sed/// the function returns true to let the declaration parsing code handle it.
1084193326Sed///
1085193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1086193326Sed///         exception-specification[opt]
1087193326Sed///
1088193326Sedbool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) {
1089193326Sed
1090193326Sed  // C++ 8.2p1:
1091193326Sed  // The ambiguity arising from the similarity between a function-style cast and
1092193326Sed  // a declaration mentioned in 6.8 can also occur in the context of a
1093193326Sed  // declaration. In that context, the choice is between a function declaration
1094193326Sed  // with a redundant set of parentheses around a parameter name and an object
1095193326Sed  // declaration with a function-style cast as the initializer. Just as for the
1096193326Sed  // ambiguities mentioned in 6.8, the resolution is to consider any construct
1097193326Sed  // that could possibly be a declaration a declaration.
1098193326Sed
1099193326Sed  TentativeParsingAction PA(*this);
1100193326Sed
1101193326Sed  ConsumeParen();
1102193326Sed  TPResult TPR = TryParseParameterDeclarationClause();
1103193326Sed  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
1104193326Sed    TPR = TPResult::False();
1105193326Sed
1106193326Sed  SourceLocation TPLoc = Tok.getLocation();
1107193326Sed  PA.Revert();
1108193326Sed
1109193326Sed  // In case of an error, let the declaration parsing code handle it.
1110193326Sed  if (TPR == TPResult::Error())
1111193326Sed    return true;
1112193326Sed
1113193326Sed  if (TPR == TPResult::Ambiguous()) {
1114193326Sed    // Function declarator has precedence over constructor-style initializer.
1115193326Sed    // Emit a warning just in case the author intended a variable definition.
1116193326Sed    if (warnIfAmbiguous)
1117193326Sed      Diag(Tok, diag::warn_parens_disambiguated_as_function_decl)
1118193326Sed        << SourceRange(Tok.getLocation(), TPLoc);
1119193326Sed    return true;
1120193326Sed  }
1121193326Sed
1122193326Sed  return TPR == TPResult::True();
1123193326Sed}
1124193326Sed
1125193326Sed/// parameter-declaration-clause:
1126193326Sed///   parameter-declaration-list[opt] '...'[opt]
1127193326Sed///   parameter-declaration-list ',' '...'
1128193326Sed///
1129193326Sed/// parameter-declaration-list:
1130193326Sed///   parameter-declaration
1131193326Sed///   parameter-declaration-list ',' parameter-declaration
1132193326Sed///
1133193326Sed/// parameter-declaration:
1134218893Sdim///   decl-specifier-seq declarator attributes[opt]
1135218893Sdim///   decl-specifier-seq declarator attributes[opt] '=' assignment-expression
1136218893Sdim///   decl-specifier-seq abstract-declarator[opt] attributes[opt]
1137218893Sdim///   decl-specifier-seq abstract-declarator[opt] attributes[opt]
1138218893Sdim///     '=' assignment-expression
1139193326Sed///
1140193326SedParser::TPResult Parser::TryParseParameterDeclarationClause() {
1141193326Sed
1142193326Sed  if (Tok.is(tok::r_paren))
1143193326Sed    return TPResult::True();
1144193326Sed
1145193326Sed  //   parameter-declaration-list[opt] '...'[opt]
1146193326Sed  //   parameter-declaration-list ',' '...'
1147193326Sed  //
1148193326Sed  // parameter-declaration-list:
1149193326Sed  //   parameter-declaration
1150193326Sed  //   parameter-declaration-list ',' parameter-declaration
1151193326Sed  //
1152193326Sed  while (1) {
1153193326Sed    // '...'[opt]
1154193326Sed    if (Tok.is(tok::ellipsis)) {
1155193326Sed      ConsumeToken();
1156193326Sed      return TPResult::True(); // '...' is a sign of a function declarator.
1157193326Sed    }
1158193326Sed
1159221345Sdim    ParsedAttributes attrs(AttrFactory);
1160218893Sdim    MaybeParseMicrosoftAttributes(attrs);
1161218893Sdim
1162193326Sed    // decl-specifier-seq
1163193326Sed    TPResult TPR = TryParseDeclarationSpecifier();
1164193326Sed    if (TPR != TPResult::Ambiguous())
1165193326Sed      return TPR;
1166193326Sed
1167193326Sed    // declarator
1168193326Sed    // abstract-declarator[opt]
1169193326Sed    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
1170193326Sed    if (TPR != TPResult::Ambiguous())
1171193326Sed      return TPR;
1172193326Sed
1173218893Sdim    // [GNU] attributes[opt]
1174218893Sdim    if (Tok.is(tok::kw___attribute))
1175218893Sdim      return TPResult::True();
1176218893Sdim
1177193326Sed    if (Tok.is(tok::equal)) {
1178193326Sed      // '=' assignment-expression
1179193326Sed      // Parse through assignment-expression.
1180218893Sdim      tok::TokenKind StopToks[2] ={ tok::comma, tok::r_paren };
1181218893Sdim      if (!SkipUntil(StopToks, 2, true/*StopAtSemi*/, true/*DontConsume*/))
1182193326Sed        return TPResult::Error();
1183193326Sed    }
1184193326Sed
1185193326Sed    if (Tok.is(tok::ellipsis)) {
1186193326Sed      ConsumeToken();
1187193326Sed      return TPResult::True(); // '...' is a sign of a function declarator.
1188193326Sed    }
1189193326Sed
1190193326Sed    if (Tok.isNot(tok::comma))
1191193326Sed      break;
1192193326Sed    ConsumeToken(); // the comma.
1193193326Sed  }
1194193326Sed
1195193326Sed  return TPResult::Ambiguous();
1196193326Sed}
1197193326Sed
1198193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
1199193326Sed/// parsing as a function declarator.
1200193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
1201193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or
1202193326Sed/// Error().
1203198092Srdivacky///
1204193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1205193326Sed///         exception-specification[opt]
1206193326Sed///
1207193326Sed/// exception-specification:
1208193326Sed///   'throw' '(' type-id-list[opt] ')'
1209193326Sed///
1210193326SedParser::TPResult Parser::TryParseFunctionDeclarator() {
1211193326Sed
1212193326Sed  // The '(' is already parsed.
1213193326Sed
1214193326Sed  TPResult TPR = TryParseParameterDeclarationClause();
1215193326Sed  if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
1216193326Sed    TPR = TPResult::False();
1217193326Sed
1218193326Sed  if (TPR == TPResult::False() || TPR == TPResult::Error())
1219193326Sed    return TPR;
1220193326Sed
1221193326Sed  // Parse through the parens.
1222193326Sed  if (!SkipUntil(tok::r_paren))
1223193326Sed    return TPResult::Error();
1224193326Sed
1225193326Sed  // cv-qualifier-seq
1226193326Sed  while (Tok.is(tok::kw_const)    ||
1227193326Sed         Tok.is(tok::kw_volatile) ||
1228193326Sed         Tok.is(tok::kw_restrict)   )
1229193326Sed    ConsumeToken();
1230193326Sed
1231218893Sdim  // ref-qualifier[opt]
1232218893Sdim  if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
1233218893Sdim    ConsumeToken();
1234218893Sdim
1235193326Sed  // exception-specification
1236193326Sed  if (Tok.is(tok::kw_throw)) {
1237193326Sed    ConsumeToken();
1238193326Sed    if (Tok.isNot(tok::l_paren))
1239193326Sed      return TPResult::Error();
1240193326Sed
1241193326Sed    // Parse through the parens after 'throw'.
1242193326Sed    ConsumeParen();
1243193326Sed    if (!SkipUntil(tok::r_paren))
1244193326Sed      return TPResult::Error();
1245193326Sed  }
1246221345Sdim  if (Tok.is(tok::kw_noexcept)) {
1247221345Sdim    ConsumeToken();
1248221345Sdim    // Possibly an expression as well.
1249221345Sdim    if (Tok.is(tok::l_paren)) {
1250221345Sdim      // Find the matching rparen.
1251221345Sdim      ConsumeParen();
1252221345Sdim      if (!SkipUntil(tok::r_paren))
1253221345Sdim        return TPResult::Error();
1254221345Sdim    }
1255221345Sdim  }
1256193326Sed
1257193326Sed  return TPResult::Ambiguous();
1258193326Sed}
1259193326Sed
1260193326Sed/// '[' constant-expression[opt] ']'
1261193326Sed///
1262193326SedParser::TPResult Parser::TryParseBracketDeclarator() {
1263193326Sed  ConsumeBracket();
1264193326Sed  if (!SkipUntil(tok::r_square))
1265193326Sed    return TPResult::Error();
1266193326Sed
1267193326Sed  return TPResult::Ambiguous();
1268193326Sed}
1269