Parse the GNU builtin expressions. This implements Parser/expressions.c:test_offsetof

llvm-svn: 38893
This commit is contained in:
Chris Lattner 2006-08-12 19:16:08 +00:00
parent 5b6032ab3c
commit 1112435558
3 changed files with 142 additions and 8 deletions

View File

@ -389,11 +389,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
/// floating-constant
/// enumeration-constant -> identifier
/// character-constant
///
/// [GNU] offsetof-member-designator:
/// [GNU] identifier
/// [GNU] offsetof-member-designator '.' identifier
/// [GNU] offsetof-member-designator '[' expression ']'
///
Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
ExprResult Res;
@ -455,9 +450,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
case tok::kw___builtin_offsetof:
case tok::kw___builtin_choose_expr:
case tok::kw___builtin_types_compatible_p:
assert(0 && "FIXME: UNIMP!");
// This can be followed by postfix-expr pieces.
return ParsePostfixExpressionSuffix(Res);
return ParseBuiltinPrimaryExpression();
case tok::plusplus: // unary-expression: '++' unary-expression
case tok::minusminus: // unary-expression: '--' unary-expression
ConsumeToken();
@ -594,6 +587,144 @@ Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
return ParseParenExpression(ExprType);
}
/// ParseBuiltinPrimaryExpression
///
/// primary-expression: [C99 6.5.1]
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
/// assign-expr ')'
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
///
/// [GNU] offsetof-member-designator:
/// [GNU] identifier
/// [GNU] offsetof-member-designator '.' identifier
/// [GNU] offsetof-member-designator '[' expression ']'
///
Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
ExprResult Res(false);
SourceLocation StartLoc = Tok.getLocation();
const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
tok::TokenKind T = Tok.getKind();
ConsumeToken(); // Eat the builtin identifier.
// All of these start with an open paren.
if (Tok.getKind() != tok::l_paren) {
Diag(Tok, diag::err_expected_lparen_after, BuiltinII->getName());
return ExprResult(true);
}
SourceLocation LParenLoc = Tok.getLocation();
ConsumeParen();
switch (T) {
default: assert(0 && "Not a builtin primary expression!");
case tok::kw___builtin_va_arg:
Res = ParseAssignmentExpression();
if (Res.isInvalid) {
SkipUntil(tok::r_paren);
return Res;
}
if (Tok.getKind() != tok::comma) {
Diag(Tok, diag::err_expected_comma);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
ParseTypeName();
break;
case tok::kw___builtin_offsetof:
ParseTypeName();
if (Tok.getKind() != tok::comma) {
Diag(Tok, diag::err_expected_comma);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
// We must have at least one identifier here.
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
while (1) {
if (Tok.getKind() == tok::period) {
// offsetof-member-designator: offsetof-member-designator '.' identifier
ConsumeToken();
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
} else if (Tok.getKind() == tok::l_square) {
// offsetof-member-designator: offsetof-member-design '[' expression ']'
SourceLocation LSquareLoc = Tok.getLocation();
ConsumeBracket();
Res = ParseExpression();
if (Res.isInvalid) {
SkipUntil(tok::r_paren);
return Res;
}
MatchRHSPunctuation(tok::r_square, LSquareLoc, "[",
diag::err_expected_rsquare);
} else {
break;
}
}
break;
case tok::kw___builtin_choose_expr:
Res = ParseAssignmentExpression();
if (Tok.getKind() != tok::comma) {
Diag(Tok, diag::err_expected_comma);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
Res = ParseAssignmentExpression();
if (Tok.getKind() != tok::comma) {
Diag(Tok, diag::err_expected_comma);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
Res = ParseAssignmentExpression();
break;
case tok::kw___builtin_types_compatible_p:
ParseTypeName();
if (Tok.getKind() != tok::comma) {
Diag(Tok, diag::err_expected_comma);
SkipUntil(tok::r_paren);
return ExprResult(true);
}
ConsumeToken();
ParseTypeName();
break;
}
MatchRHSPunctuation(tok::r_paren, LParenLoc, "(",
diag::err_expected_rparen);
// These can be followed by postfix-expr pieces because they are
// primary-expressions.
return ParsePostfixExpressionSuffix(Res);
}
/// ParseStringLiteralExpression - This handles the various token types that
/// form string literals, and also handles string concatenation [C99 5.1.1.2,
/// translation phase #6].

View File

@ -293,6 +293,8 @@ DIAG(err_expected_statement, ERROR,
"expected statement")
DIAG(err_expected_lparen_after, ERROR,
"expected '(' after '%s'")
DIAG(err_expected_comma, ERROR,
"expected ','")
DIAG(err_expected_lbrace_in_compound_literal, ERROR,
"expected '{' in compound literal")
DIAG(err_expected_while, ERROR,

View File

@ -186,6 +186,7 @@ private:
ExprResult ParseCastExpression(bool isUnaryExpression);
ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
ExprResult ParseSizeofAlignofExpression();
ExprResult ParseBuiltinPrimaryExpression();
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {