[cfe-commits] r57131 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseTentative.cpp test/SemaCXX/decl-expr-ambiguity.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Sun Oct 5 12:56:23 PDT 2008
Author: akirtzidis
Date: Sun Oct 5 14:56:22 2008
New Revision: 57131
URL: http://llvm.org/viewvc/llvm-project?rev=57131&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=57131&r1=57130&r2=57131&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Oct 5 14:56:22 2008
@@ -591,6 +591,15 @@
return isDeclarationSpecifier();
}
+ /// isTypeIdInParens - 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.
+ bool isTypeIdInParens() {
+ if (getLang().CPlusPlus)
+ return isCXXTypeIdInParens();
+ return isTypeSpecifierQualifier();
+ }
+
/// isCXXDeclarationStatement - C++-specialized function that disambiguates
/// between a declaration or an expression statement, when parsing function
/// bodies. Returns true for declaration, false for expression.
@@ -617,6 +626,13 @@
/// the function returns true to let the declaration parsing code handle it.
bool isCXXConditionDeclaration();
+ /// 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.
+ bool isCXXTypeIdInParens();
+
/// TPResult - Used as the result value for functions whose purpose is to
/// disambiguate C++ constructs by "tentatively parsing" them.
/// This is a class instead of a simple enum because the implicit enum-to-bool
@@ -659,7 +675,7 @@
TPResult TryParseSimpleDeclaration();
TPResult TryParseTypeofSpecifier();
TPResult TryParseInitDeclaratorList();
- TPResult TryParseDeclarator(bool mayBeAbstract);
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
TPResult TryParseParameterDeclarationClause();
TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator();
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=57131&r1=57130&r2=57131&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sun Oct 5 14:56:22 2008
@@ -1581,7 +1581,7 @@
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
- if (isTypeSpecifierQualifier()) {
+ if (isTypeIdInParens()) {
TypeTy *Ty = ParseTypeName();
assert(Ty && "Parser::ParseTypeofSpecifier(): missing type");
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=57131&r1=57130&r2=57131&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sun Oct 5 14:56:22 2008
@@ -981,7 +981,7 @@
if (!Stmt.isInvalid && Tok.is(tok::r_paren))
Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.Val, Tok.getLocation());
- } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
+ } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
// Otherwise, this is a compound literal expression or cast expression.
TypeTy *Ty = ParseTypeName();
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=57131&r1=57130&r2=57131&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sun Oct 5 14:56:22 2008
@@ -282,6 +282,58 @@
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 @@
/// '~' 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 @@
// 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 @@
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))
Modified: cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp?rev=57131&r1=57130&r2=57131&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp Sun Oct 5 14:56:22 2008
@@ -13,6 +13,8 @@
void(a), ++a; // expected-warning {{statement was disambiguated as expression}} expected-warning {{expression result unused}}
if (int(a)+1) {}
for (int(a)+1;;) {}
+ a = sizeof(int()+1);
+ typeof(int()+1) a2;
// Declarations.
T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}}
More information about the cfe-commits
mailing list