aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTentative.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-05 19:56:22 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-05 19:56:22 +0000
commit78c8d80f19cb0bccd4f3d590e71a230e727cfab5 (patch)
tree33e90db48d74ecb686e1f5c93e4a970c9354e149 /lib/Parse/ParseTentative.cpp
parent9b533164570a67c81ad49f3691f02608530a042e (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.cpp59
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))