diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-10-05 19:56:22 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-10-05 19:56:22 +0000 |
commit | 78c8d80f19cb0bccd4f3d590e71a230e727cfab5 (patch) | |
tree | 33e90db48d74ecb686e1f5c93e4a970c9354e149 /lib/Parse/ParseTentative.cpp | |
parent | 9b533164570a67c81ad49f3691f02608530a042e (diff) |
Handle ambiguities between expressions and type-ids that occur inside parentheses, e.g.:
sizeof(int()) -> "int()" is type-id
sizeof(int()+1) -> "int()+1" is expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57131 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseTentative.cpp')
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 2f1130ad74..9bd35dd110 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -282,6 +282,58 @@ bool Parser::isCXXConditionDeclaration() { return TPR == TPResult::True(); } +/// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to
+/// know whether the parens contain an expression or a type-id.
+/// Returns true for a type-id and false for an expression.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// type-id:
+/// type-specifier-seq abstract-declarator[opt] +/// +bool Parser::isCXXTypeIdInParens() { + TPResult TPR = isCXXDeclarationSpecifier(); + if (TPR != TPResult::Ambiguous()) + return TPR != TPResult::False(); // Returns true for TPResult::True() or + // TPResult::Error(). + + // FIXME: Add statistics about the number of ambiguous statements encountered + // and how they were resolved (number of declarations+number of expressions). + + // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. + // We need tentative parsing... + + TentativeParsingAction PA(*this); + + // type-specifier-seq + if (Tok.is(tok::kw_typeof)) + TryParseTypeofSpecifier(); + else + ConsumeToken(); + assert(Tok.is(tok::l_paren) && "Expected '('"); + + // declarator + TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); + + // In case of an error, let the declaration parsing code handle it. + if (TPR == TPResult::Error()) + TPR = TPResult::True(); + + if (TPR == TPResult::Ambiguous()) { + // We are supposed to be inside parens, so if after the abstract declarator + // we encounter a ')' this is a type-id, otherwise it's an expression. + if (Tok.is(tok::r_paren)) + TPR = TPResult::True(); + else + TPR = TPResult::False(); + } + + PA.Revert(); + + assert(TPR == TPResult::True() || TPR == TPResult::False()); + return TPR == TPResult::True(); +} + /// declarator: /// direct-declarator /// ptr-operator declarator @@ -332,7 +384,8 @@ bool Parser::isCXXConditionDeclaration() { /// '~' class-name [TODO] /// template-id [TODO] /// -Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract) { +Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, + bool mayHaveIdentifier) { // declarator: // direct-declarator // ptr-operator declarator @@ -353,7 +406,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract) { // direct-declarator: // direct-abstract-declarator: - if (Tok.is(tok::identifier)) { + if (Tok.is(tok::identifier) && mayHaveIdentifier) { // declarator-id ConsumeToken(); } else if (Tok.is(tok::l_paren)) { @@ -370,7 +423,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract) { ConsumeParen(); if (Tok.is(tok::kw___attribute)) return TPResult::True(); // attributes indicate declaration - TPResult TPR = TryParseDeclarator(mayBeAbstract); + TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); if (TPR != TPResult::Ambiguous()) return TPR; if (Tok.isNot(tok::r_paren)) |