[cfe-commits] r38897 - in /cfe/cfe/trunk: Parse/ParseDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Parser.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:25:35 PDT 2007
Author: sabre
Date: Wed Jul 11 11:25:34 2007
New Revision: 38897
URL: http://llvm.org/viewvc/llvm-project?rev=38897&view=rev
Log:
Parse struct/union specifiers.
Modified:
cfe/cfe/trunk/Parse/ParseDecl.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=38897&r1=38896&r2=38897&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:25:34 2007
@@ -26,24 +26,7 @@
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;
- }
+ ParseSpecifierQualifierList(DS);
// Parse the abstract-declarator, if present.
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
@@ -102,6 +85,33 @@
}
}
+/// ParseSpecifierQualifierList
+/// specifier-qualifier-list:
+/// type-specifier specifier-qualifier-list[opt]
+/// type-qualifier specifier-qualifier-list[opt]
+///
+void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
+ /// specifier-qualifier-list is a subset of declaration-specifiers. Just
+ /// parse declaration-specifiers and complain about extra stuff.
+ 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;
+ }
+}
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
@@ -128,7 +138,7 @@
/// 'double'
/// 'signed'
/// 'unsigned'
-/// struct-or-union-specifier [TODO]
+/// struct-or-union-specifier
/// enum-specifier
/// typedef-name [TODO]
/// [C99] '_Bool'
@@ -240,8 +250,10 @@
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
break;
- //case tok::kw_struct:
- //case tok::kw_union:
+ case tok::kw_struct:
+ case tok::kw_union:
+ ParseStructUnionSpecifier(DS);
+ continue;
case tok::kw_enum:
ParseEnumSpecifier(DS);
continue;
@@ -278,17 +290,124 @@
}
}
+
+/// ParseStructUnionSpecifier
+/// struct-or-union-specifier: [C99 6.7.2.1]
+/// struct-or-union identifier[opt] '{' struct-declaration-list '}'
+/// struct-or-union identifier
+/// struct-or-union:
+/// 'struct'
+/// 'union'
+/// struct-declaration-list:
+/// struct-declaration
+/// struct-declaration-list struct-declaration
+/// struct-declaration:
+/// specifier-qualifier-list struct-declarator-list ';'
+/// struct-declarator-list:
+/// struct-declarator
+/// struct-declarator-list ',' struct-declarator
+/// struct-declarator:
+/// declarator
+/// declarator[opt] ':' constant-expression
+///
+void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
+ assert((Tok.getKind() == tok::kw_struct ||
+ Tok.getKind() == tok::kw_union) && "Not a struct/union specifier");
+ bool isUnion = Tok.getKind() == tok::kw_union;
+ ConsumeToken();
+
+ // Must have either 'struct name' or 'struct {...}'.
+ if (Tok.getKind() != tok::identifier &&
+ Tok.getKind() != tok::l_brace) {
+ Diag(Tok, diag::err_expected_ident_lbrace);
+ return;
+ }
+
+ if (Tok.getKind() == tok::identifier)
+ ConsumeToken();
+
+ if (Tok.getKind() != tok::l_brace)
+ return;
+
+ SourceLocation LBraceLoc = Tok.getLocation();
+ ConsumeBrace();
+
+ if (Tok.getKind() == tok::r_brace)
+ Diag(Tok, diag::ext_empty_struct_union_enum, isUnion ? "union" : "struct");
+
+ while (Tok.getKind() != tok::r_brace &&
+ Tok.getKind() != tok::eof) {
+ // Each iteration of this loop reads one struct-declaration.
+
+ // Parse the common specifier-qualifiers-list piece.
+ DeclSpec DS;
+ SourceLocation SpecQualLoc = Tok.getLocation();
+ ParseSpecifierQualifierList(DS);
+ // TODO: Does specifier-qualifier list correctly check that *something* is
+ // specified?
+
+ Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+
+ // If there are no declarators, issue a warning.
+ if (Tok.getKind() == tok::semi) {
+ Diag(SpecQualLoc, diag::w_no_declarators);
+ } else {
+ // Read struct-declarators until we find the semicolon.
+ while (1) {
+ /// struct-declarator: declarator
+ /// struct-declarator: declarator[opt] ':' constant-expression
+ if (Tok.getKind() != tok::colon)
+ ParseDeclarator(DeclaratorInfo);
+
+ if (Tok.getKind() == tok::colon) {
+ ConsumeToken();
+ ExprResult Res = ParseConstantExpression();
+ if (Res.isInvalid) {
+ SkipUntil(tok::semi, true, true);
+ } else {
+ // Process it.
+ }
+ }
+
+ // TODO: install declarator.
+
+ // If we don't have a comma, it is either the end of the list (a ';') or
+ // an error, bail out.
+ if (Tok.getKind() != tok::comma)
+ break;
+
+ // Consume the comma.
+ ConsumeToken();
+
+ // Parse the next declarator.
+ DeclaratorInfo.clear();
+ }
+ }
+
+ if (Tok.getKind() == tok::semi) {
+ ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_expected_semi_decl_list);
+ // Skip to end of block or statement
+ SkipUntil(tok::r_brace, true, true);
+ }
+ }
+
+ MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",diag::err_expected_rbrace);
+}
+
+
/// ParseEnumSpecifier
-/// enum-specifier:
+/// enum-specifier: [C99 6.7.2.2]
/// 'enum' identifier[opt] '{' enumerator-list '}'
/// [C99] 'enum' identifier[opt] '{' enumerator-list ',' '}'
/// 'enum' identifier
/// enumerator-list:
/// enumerator
-/// enumerator-list , enumerator
+/// enumerator-list ',' enumerator
/// enumerator:
/// enumeration-constant
-/// enumeration-constant = constant-expression
+/// enumeration-constant '=' constant-expression
/// enumeration-constant:
/// identifier
///
@@ -306,33 +425,37 @@
if (Tok.getKind() == tok::identifier)
ConsumeToken();
- if (Tok.getKind() == tok::l_brace) {
- SourceLocation LBraceLoc = Tok.getLocation();
- ConsumeBrace();
+ if (Tok.getKind() != tok::l_brace)
+ return;
+
+ SourceLocation LBraceLoc = Tok.getLocation();
+ ConsumeBrace();
+
+ if (Tok.getKind() == tok::r_brace)
+ Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
+
+ // Parse the enumerator-list.
+ while (Tok.getKind() == tok::identifier) {
+ ConsumeToken();
- // Parse the enumerator-list.
- while (Tok.getKind() == tok::identifier) {
- ConsumeToken();
-
- if (Tok.getKind() == tok::equal) {
- ConsumeToken();
- ExprResult Res = ParseConstantExpression();
- if (Res.isInvalid) SkipUntil(tok::comma, true, false);
- }
-
- if (Tok.getKind() != tok::comma)
- break;
- SourceLocation CommaLoc = Tok.getLocation();
+ if (Tok.getKind() == tok::equal) {
ConsumeToken();
-
- if (Tok.getKind() != tok::identifier && !getLang().C99)
- Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
+ ExprResult Res = ParseConstantExpression();
+ if (Res.isInvalid) SkipUntil(tok::comma, true, false);
}
- // Eat the }.
- MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",
- diag::err_expected_rbrace);
+ if (Tok.getKind() != tok::comma)
+ break;
+ SourceLocation CommaLoc = Tok.getLocation();
+ ConsumeToken();
+
+ if (Tok.getKind() != tok::identifier && !getLang().C99)
+ Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
}
+
+ // Eat the }.
+ MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",
+ diag::err_expected_rbrace);
// TODO: semantic analysis on the declspec for enums.
}
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38897&r1=38896&r2=38897&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:25:34 2007
@@ -236,6 +236,8 @@
DIAG(w_type_defaults_to_int, WARNING,
"type defaults to 'int'")
+DIAG(w_no_declarators, WARNING,
+ "declaration does not declare anything")
DIAG(ext_empty_source_file, EXTENSION,
"ISO C forbids an empty source file")
@@ -250,6 +252,9 @@
DIAG(ext_thread_before, EXTENSION,
"'__thread' before 'static'")
+DIAG(ext_empty_struct_union_enum, EXTENSION,
+ "use of empty %s extension")
+
DIAG(ext_ident_list_in_param, EXTENSION,
"type-less parameter names in function declaration")
DIAG(ext_c99_array_usage, EXTENSION,
Modified: cfe/cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Parser.h?rev=38897&r1=38896&r2=38897&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:25:34 2007
@@ -242,7 +242,10 @@
void ParseDeclaration(unsigned Context);
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
void ParseDeclarationSpecifiers(DeclSpec &DS);
+ void ParseSpecifierQualifierList(DeclSpec &DS);
+
void ParseEnumSpecifier(DeclSpec &DS);
+ void ParseStructUnionSpecifier(DeclSpec &DS);
bool isDeclarationSpecifier() const;
bool isTypeSpecifierQualifier() const;
More information about the cfe-commits
mailing list