Refactor the common code of 'ParseTypeofSpecifier' and 'ParseSizeofAlignofExpression' into a new

'ParseExprAfterTypeofSizeofAlignof' method.

llvm-svn: 72256
This commit is contained in:
Argyrios Kyrtzidis 2009-05-22 10:22:50 +00:00
parent f5cc7ac4d5
commit 7bd98440b3
3 changed files with 109 additions and 65 deletions

View File

@ -158,6 +158,8 @@ public:
OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); }
// Parsing methods.
/// ParseTranslationUnit - All in one method that initializes parses, and
@ -663,6 +665,11 @@ private:
OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
OwningExprResult ParseSizeofAlignofExpression();
OwningExprResult ParseBuiltinPrimaryExpression();
OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
TypeTy *&CastTy,
SourceRange &CastRange);
static const unsigned ExprListSize = 12;
typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;

View File

@ -2648,51 +2648,35 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
///
void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
assert(Tok.is(tok::kw_typeof) && "Not a typeof specifier");
const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
Token OpTok = Tok;
SourceLocation StartLoc = ConsumeToken();
// If the operand doesn't start with an '(', it must be an expression.
OwningExprResult Operand(Actions);
if (Tok.isNot(tok::l_paren)) {
if (!getLang().CPlusPlus) {
Diag(Tok, diag::err_expected_lparen_after_id) << BuiltinII;
return;
}
Operand = ParseCastExpression(true/*isUnaryExpression*/);
bool isCastExpr;
TypeTy *CastTy;
SourceRange CastRange;
OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
isCastExpr,
CastTy,
CastRange);
if (CastRange.getEnd().isInvalid())
// FIXME: Not accurate, the range gets one token more than it should.
DS.SetRangeEnd(Tok.getLocation());
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
// literal, or starts with a primary-expression that is a parenthesized
// expression.
ParenParseOption ExprType = CastExpr;
TypeTy *CastTy;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
Operand = ParseParenExpression(ExprType, CastTy, RParenLoc);
DS.SetRangeEnd(RParenLoc);
// If ParseParenExpression parsed a '(typename)' sequence only, then this is
// typeof a type. Otherwise, it is typeof an expression.
if (ExprType == CastExpr) {
if (!CastTy) {
DS.SetTypeSpecError();
return;
}
const char *PrevSpec = 0;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
CastTy))
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
else
DS.SetRangeEnd(CastRange.getEnd());
if (isCastExpr) {
if (!CastTy) {
DS.SetTypeSpecError();
return;
}
// If this is a parenthesized expression, it is the start of a
// unary-expression, but doesn't include any postfix pieces. Parse these
// now if present.
Operand = ParsePostfixExpressionSuffix(move(Operand));
const char *PrevSpec = 0;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
CastTy))
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
return;
}
// If we get here, the operand to the typeof was an expresion.

View File

@ -913,6 +913,72 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
}
}
/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
/// we are at the start of an expression or a parenthesized type-id.
/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
/// (isCastExpr == false) or the type (isCastExpr == true).
///
/// unary-expression: [C99 6.5.3]
/// 'sizeof' unary-expression
/// 'sizeof' '(' type-name ')'
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
/// [C++0x] 'alignof' '(' type-id ')'
///
/// [GNU] typeof-specifier:
/// typeof ( expressions )
/// typeof ( type-name )
/// [GNU/C++] typeof unary-expression
///
Parser::OwningExprResult
Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
TypeTy *&CastTy,
SourceRange &CastRange) {
assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
"Not a typeof/sizeof/alignof expression!");
OwningExprResult Operand(Actions);
// If the operand doesn't start with an '(', it must be an expression.
if (Tok.isNot(tok::l_paren)) {
isCastExpr = false;
if (OpTok.is(tok::kw_typeof) && !getLang().CPlusPlus) {
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
return ExprError();
}
Operand = ParseCastExpression(true/*isUnaryExpression*/);
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
// literal, or starts with a primary-expression that is a parenthesized
// expression.
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
Operand = ParseParenExpression(ExprType, CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
// If ParseParenExpression parsed a '(typename)' sequence only, then this is
// a type.
if (ExprType == CastExpr) {
isCastExpr = true;
return ExprEmpty();
}
// If this is a parenthesized expression, it is the start of a
// unary-expression, but doesn't include any postfix pieces. Parse these
// now if present.
Operand = ParsePostfixExpressionSuffix(move(Operand));
}
// If we get here, the operand to the typeof/sizeof/alignof was an expresion.
isCastExpr = false;
return move(Operand);
}
/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
/// unary-expression: [C99 6.5.3]
@ -928,40 +994,26 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
Token OpTok = Tok;
ConsumeToken();
// If the operand doesn't start with an '(', it must be an expression.
OwningExprResult Operand(Actions);
if (Tok.isNot(tok::l_paren)) {
Operand = ParseCastExpression(true);
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
// literal, or starts with a primary-expression that is a parenthesized
// expression.
ParenParseOption ExprType = CastExpr;
TypeTy *CastTy;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
Operand = ParseParenExpression(ExprType, CastTy, RParenLoc);
bool isCastExpr;
TypeTy *CastTy;
SourceRange CastRange;
OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
isCastExpr,
CastTy,
CastRange);
// If ParseParenExpression parsed a '(typename)' sequence only, the this is
// sizeof/alignof a type. Otherwise, it is sizeof/alignof an expression.
if (ExprType == CastExpr)
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/true, CastTy,
SourceRange(LParenLoc, RParenLoc));
// If this is a parenthesized expression, it is the start of a
// unary-expression, but doesn't include any postfix pieces. Parse these
// now if present.
Operand = ParsePostfixExpressionSuffix(move(Operand));
}
if (isCastExpr)
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/true, CastTy,
CastRange);
// If we get here, the operand to the sizeof/alignof was an expresion.
if (!Operand.isInvalid())
Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
/*isType=*/false,
Operand.release(), SourceRange());
Operand.release(), CastRange);
return move(Operand);
}
@ -1177,6 +1229,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType,
Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
} else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
// Otherwise, this is a compound literal expression or cast expression.
TypeResult Ty = ParseTypeName();