Parse the GNU builtin expressions. This implements Parser/expressions.c:test_offsetof
llvm-svn: 38893
This commit is contained in:
parent
5b6032ab3c
commit
1112435558
|
@ -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].
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue