forked from OSchip/llvm-project
Implement type-name parsing, and simple compound initializer parsing.
llvm-svn: 38865
This commit is contained in:
parent
4564bc1123
commit
f5fbd7963d
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue