Implement type-name parsing, and simple compound initializer parsing.

llvm-svn: 38865
This commit is contained in:
Chris Lattner 2006-08-10 23:56:11 +00:00
parent 4564bc1123
commit f5fbd7963d
4 changed files with 114 additions and 6 deletions

View File

@ -20,6 +20,37 @@ using namespace clang;
// C99 6.7: Declarations.
//===----------------------------------------------------------------------===//
/// ParseTypeName
/// type-name: [C99 6.7.6]
/// specifier-qualifier-list abstract-declarator[opt]
void Parser::ParseTypeName() {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
SourceLocation Loc = Tok.getLocation();
ParseDeclarationSpecifiers(DS);
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
if (Specs == DeclSpec::PQ_None)
Diag(Tok, diag::err_typename_requires_specqual);
if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
Diag(Loc, diag::err_typename_invalid_storageclass);
// Remove storage class.
DS.StorageClassSpec = DeclSpec::SCS_unspecified;
DS.SCS_thread_specified = false;
}
if (Specs & DeclSpec::PQ_FunctionSpecifier) {
Diag(Loc, diag::err_typename_invalid_functionspec);
DS.FS_inline_specified = false;
}
// Parse the abstract-declarator, if present.
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
/// 'Context' should be a Declarator::TheContext value.
@ -244,6 +275,49 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
}
}
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
bool Parser::isTypeSpecifierQualifier() const {
switch (Tok.getKind()) {
default: return false;
// type-specifiers
case tok::kw_short:
case tok::kw_long:
case tok::kw_signed:
case tok::kw_unsigned:
case tok::kw__Complex:
case tok::kw__Imaginary:
case tok::kw_void:
case tok::kw_char:
case tok::kw_int:
case tok::kw_float:
case tok::kw_double:
case tok::kw__Bool:
case tok::kw__Decimal32:
case tok::kw__Decimal64:
case tok::kw__Decimal128:
// struct-or-union-specifier
case tok::kw_struct:
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
// type-qualifier
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
return true;
// typedef-name
case tok::identifier:
// FIXME: if this is a typedef return true.
return false;
// TODO: Attributes.
}
}
/// isDeclarationSpecifier() - Return true if the current token is part of a
/// declaration specifier.
bool Parser::isDeclarationSpecifier() const {
@ -279,13 +353,16 @@ bool Parser::isDeclarationSpecifier() const {
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
// type-qualifier
case tok::kw_const:
case tok::kw_volatile:
case tok::kw_restrict:
// function-specifier
case tok::kw_inline:
return true;
// typedef-name
case tok::identifier:
// FIXME: if this is a typedef return true.

View File

@ -19,6 +19,15 @@ using namespace clang;
// C99 6.7.8
void Parser::ParseInitializer() {
// FIXME: STUB.
if (Tok.getKind() == tok::l_brace) {
ConsumeBrace();
// FIXME: initializer-list
// Match the '}'.
MatchRHSPunctuation(tok::r_brace, Tok.getLocation(), "{",
diag::err_expected_rbrace);
return;
}
ParseAssignmentExpression();
}
@ -44,10 +53,12 @@ void Parser::ParseCastExpression() {
if (Tok.getKind() != tok::l_paren)
return ParseUnaryExpression();
#if 0
// Otherwise this is either a cast, a compound literal, or a parenthesized
// expression.
SourceLocation LParenLoc = Tok.getLocation();
ConsumeParen();
#endif
assert(0);
}
@ -319,11 +330,22 @@ void Parser::ParseParenExpression(bool ParenExprOnly) {
!getLang().NoExtensions) {
Diag(Tok, diag::ext_gnu_statement_expr);
ParseCompoundStatement();
} else if (!ParenExprOnly && isTypeSpecifierQualifier()) {
// FIXME: Implement compound literals: C99 6.5.2.5. Type-name: C99 6.7.6.
assert(0 && "IMPLEMENT THIS!");
} else {
} else if (ParenExprOnly || !isTypeSpecifierQualifier()) {
ParseExpression();
} else {
// Otherwise, this is a compound expression.
ParseTypeName();
// Match the ')'.
MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
if (Tok.getKind() != tok::l_brace) {
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return;
}
ParseInitializer();
return;
}

View File

@ -288,6 +288,8 @@ DIAG(err_expected_statement, ERROR,
"expected statement")
DIAG(err_expected_lparen_after, ERROR,
"expected '(' after '%s'")
DIAG(err_expected_lbrace_in_compound_literal, ERROR,
"expected '{' in compound literal")
DIAG(err_expected_while, ERROR,
"expected 'while' in do/while loop")
DIAG(err_expected_semi_after, ERROR,
@ -306,7 +308,12 @@ DIAG(err_label_end_of_compound_statement, ERROR,
DIAG(err_matching, ERROR,
"to match this '%s'")
DIAG(err_typename_requires_specqual, ERROR,
"type name requires a specifier or qualifier")
DIAG(err_typename_invalid_storageclass, ERROR,
"type name does not allow storage class to be specified")
DIAG(err_typename_invalid_functionspec, ERROR,
"type name does not allow function specifier to be specified")
DIAG(err_invalid_decl_spec_combination, ERROR,
"cannot combine with previous '%s' declaration specifier")
DIAG(err_invalid_sign_spec, ERROR,

View File

@ -204,7 +204,9 @@ private:
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
void ParseDeclarationSpecifiers(DeclSpec &DS);
bool isDeclarationSpecifier() const;
bool isTypeSpecifierQualifier() const { return false; } // FIXME!
bool isTypeSpecifierQualifier() const;
void ParseTypeName();
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
void ParseDeclarator(Declarator &D);