forked from OSchip/llvm-project
Implement parsing of array declarators like:
int Array[*(int*)P+A]; llvm-svn: 38890
This commit is contained in:
parent
3b51ddf438
commit
6259172911
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue