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.
|
// 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
|
/// ParseDeclaration - Parse a full 'declaration', which consists of
|
||||||
/// declaration-specifiers, some number of declarators, and a semicolon.
|
/// declaration-specifiers, some number of declarators, and a semicolon.
|
||||||
/// 'Context' should be a Declarator::TheContext value.
|
/// '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
|
/// isDeclarationSpecifier() - Return true if the current token is part of a
|
||||||
/// declaration specifier.
|
/// declaration specifier.
|
||||||
bool Parser::isDeclarationSpecifier() const {
|
bool Parser::isDeclarationSpecifier() const {
|
||||||
|
@ -279,13 +353,16 @@ bool Parser::isDeclarationSpecifier() const {
|
||||||
case tok::kw_union:
|
case tok::kw_union:
|
||||||
// enum-specifier
|
// enum-specifier
|
||||||
case tok::kw_enum:
|
case tok::kw_enum:
|
||||||
|
|
||||||
// type-qualifier
|
// type-qualifier
|
||||||
case tok::kw_const:
|
case tok::kw_const:
|
||||||
case tok::kw_volatile:
|
case tok::kw_volatile:
|
||||||
case tok::kw_restrict:
|
case tok::kw_restrict:
|
||||||
|
|
||||||
// function-specifier
|
// function-specifier
|
||||||
case tok::kw_inline:
|
case tok::kw_inline:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// typedef-name
|
// typedef-name
|
||||||
case tok::identifier:
|
case tok::identifier:
|
||||||
// FIXME: if this is a typedef return true.
|
// FIXME: if this is a typedef return true.
|
||||||
|
|
|
@ -19,6 +19,15 @@ using namespace clang;
|
||||||
// C99 6.7.8
|
// C99 6.7.8
|
||||||
void Parser::ParseInitializer() {
|
void Parser::ParseInitializer() {
|
||||||
// FIXME: STUB.
|
// 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();
|
ParseAssignmentExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,10 +53,12 @@ void Parser::ParseCastExpression() {
|
||||||
if (Tok.getKind() != tok::l_paren)
|
if (Tok.getKind() != tok::l_paren)
|
||||||
return ParseUnaryExpression();
|
return ParseUnaryExpression();
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Otherwise this is either a cast, a compound literal, or a parenthesized
|
// Otherwise this is either a cast, a compound literal, or a parenthesized
|
||||||
// expression.
|
// expression.
|
||||||
SourceLocation LParenLoc = Tok.getLocation();
|
SourceLocation LParenLoc = Tok.getLocation();
|
||||||
ConsumeParen();
|
ConsumeParen();
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
@ -319,11 +330,22 @@ void Parser::ParseParenExpression(bool ParenExprOnly) {
|
||||||
!getLang().NoExtensions) {
|
!getLang().NoExtensions) {
|
||||||
Diag(Tok, diag::ext_gnu_statement_expr);
|
Diag(Tok, diag::ext_gnu_statement_expr);
|
||||||
ParseCompoundStatement();
|
ParseCompoundStatement();
|
||||||
} else if (!ParenExprOnly && isTypeSpecifierQualifier()) {
|
} else if (ParenExprOnly || !isTypeSpecifierQualifier()) {
|
||||||
// FIXME: Implement compound literals: C99 6.5.2.5. Type-name: C99 6.7.6.
|
|
||||||
assert(0 && "IMPLEMENT THIS!");
|
|
||||||
} else {
|
|
||||||
ParseExpression();
|
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")
|
"expected statement")
|
||||||
DIAG(err_expected_lparen_after, ERROR,
|
DIAG(err_expected_lparen_after, ERROR,
|
||||||
"expected '(' after '%s'")
|
"expected '(' after '%s'")
|
||||||
|
DIAG(err_expected_lbrace_in_compound_literal, ERROR,
|
||||||
|
"expected '{' in compound literal")
|
||||||
DIAG(err_expected_while, ERROR,
|
DIAG(err_expected_while, ERROR,
|
||||||
"expected 'while' in do/while loop")
|
"expected 'while' in do/while loop")
|
||||||
DIAG(err_expected_semi_after, ERROR,
|
DIAG(err_expected_semi_after, ERROR,
|
||||||
|
@ -306,7 +308,12 @@ DIAG(err_label_end_of_compound_statement, ERROR,
|
||||||
DIAG(err_matching, ERROR,
|
DIAG(err_matching, ERROR,
|
||||||
"to match this '%s'")
|
"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,
|
DIAG(err_invalid_decl_spec_combination, ERROR,
|
||||||
"cannot combine with previous '%s' declaration specifier")
|
"cannot combine with previous '%s' declaration specifier")
|
||||||
DIAG(err_invalid_sign_spec, ERROR,
|
DIAG(err_invalid_sign_spec, ERROR,
|
||||||
|
|
|
@ -204,7 +204,9 @@ private:
|
||||||
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
|
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
|
||||||
void ParseDeclarationSpecifiers(DeclSpec &DS);
|
void ParseDeclarationSpecifiers(DeclSpec &DS);
|
||||||
bool isDeclarationSpecifier() const;
|
bool isDeclarationSpecifier() const;
|
||||||
bool isTypeSpecifierQualifier() const { return false; } // FIXME!
|
bool isTypeSpecifierQualifier() const;
|
||||||
|
|
||||||
|
void ParseTypeName();
|
||||||
|
|
||||||
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
|
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
|
||||||
void ParseDeclarator(Declarator &D);
|
void ParseDeclarator(Declarator &D);
|
||||||
|
|
Loading…
Reference in New Issue