Implement parsing of array declarators like:

int Array[*(int*)P+A];

llvm-svn: 38890
This commit is contained in:
Chris Lattner 2006-08-12 18:40:58 +00:00
parent 3b51ddf438
commit 6259172911
4 changed files with 48 additions and 18 deletions

View File

@ -717,7 +717,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
void *NumElts = 0;
ExprResult NumElements(false);
if (Tok.getKind() == tok::star) {
// Remember the '*' token, in case we have to un-get it.
LexerToken StarTok = Tok;
@ -733,22 +733,19 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
} else {
// Otherwise, the * must have been some expression (such as '*ptr') that
// started an assignment-expr. We already consumed the token, but now we
// need to reparse it.
// FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
// macro expansion context, so they will be read again. It is basically
// impossible to refudge the * in otherwise, due to cases like X[*p + 4].
assert(0 && "FIXME: int X[*p] unimplemented");
// need to reparse it. This handles cases like 'X[*p + 4]'
NumElements = ParseAssignmentExpressionWithLeadingStar(StarTok);
}
} else if (Tok.getKind() != tok::r_square) {
// Parse the assignment-expression now.
ExprResult Res = ParseAssignmentExpression();
if (Res.isInvalid) {
// If the expression was invalid, skip it.
SkipUntil(tok::r_square);
return;
}
NumElts = /*TODO: parse array size expr*/0;
NumElements = ParseAssignmentExpression();
}
// If there was an error parsing the assignment-expression, recover.
if (NumElements.isInvalid) {
// If the expression was invalid, skip it.
SkipUntil(tok::r_square);
return;
}
MatchRHSPunctuation(tok::r_square, StartLoc, "[", diag::err_expected_rsquare);
@ -757,13 +754,13 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// it was not a constant expression.
if (!getLang().C99) {
// TODO: check C90 array constant exprness.
if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
if (isStar || StaticLoc.isValid() || 0/*FIXME: NumElts is constantexpr*/)
Diag(StartLoc, diag::ext_c99_array_usage);
}
// Remember that we parsed a pointer type, and remember the type-quals.
D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
StaticLoc.isValid(), isStar,
NumElts, StartLoc));
NumElements.Val, StartLoc));
}

View File

@ -233,6 +233,39 @@ ParseExpressionWithLeadingIdentifier(const LexerToken &Tok) {
return ParseRHSOfBinaryExpression(Res, prec::Comma);
}
/// ParseAssignmentExpressionWithLeadingStar - This special purpose method is
/// used in contexts where we have already consumed a '*' (which we saved in
/// 'Tok'), then discovered that the '*' was really the leading token of an
/// expression. For example, in "*(int*)P+B", we consumed "*" (which is
/// now in 'Tok') and the current token is "(".
Parser::ExprResult Parser::
ParseAssignmentExpressionWithLeadingStar(const LexerToken &Tok) {
// We know that 'Tok' must correspond to this production:
// unary-expression: unary-operator cast-expression
// where 'unary-operator' is '*'.
// Parse the cast-expression that follows the '*'. This will parse the
// "*(int*)P" part of "*(int*)P+B".
ExprResult Res = ParseCastExpression(false);
if (Res.isInvalid) return Res;
// TODO: Combine Tok + Res to get the new AST.
// We have to parse an entire cast-expression before starting the
// ParseRHSOfBinaryExpression method (which parses any trailing binops). Since
// we know that the only production above us is the cast-expression
// production, and because the only alternative productions start with a '('
// token (we know we had a '*'), there is no work to do to get a whole
// cast-expression.
// At this point, the "*(int*)P" part of "*(int*)P+B" has been consumed. Once
// this is done, we can invoke ParseRHSOfBinaryExpression to consume any
// trailing operators (e.g. "+" in this example) and connected chunks of the
// assignment-expression.
return ParseRHSOfBinaryExpression(Res, prec::Assignment);
}
/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
/// LHS and has a precedence of at least MinPrec.
Parser::ExprResult
@ -309,7 +342,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
}
}
/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
/// true, parse a unary-expression.
///

View File

@ -224,7 +224,7 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.getKind() == tok::semi)
assert(0 && "Unimp!");
assert(0 && "Unimp!"); // FIXME: implement 'struct foo;'.
// Parse the first declarator.

View File

@ -179,6 +179,7 @@ private:
// C99 6.5: Expressions.
//ExprResult ParseExpression(); // Above.
ExprResult ParseExpressionWithLeadingIdentifier(const LexerToken &Tok);
ExprResult ParseAssignmentExpressionWithLeadingStar(const LexerToken &Tok);
ExprResult ParseAssignmentExpression(); // Expr that doesn't include commas.
ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec);