Parse attributes in all places allowed.

llvm-svn: 38925
This commit is contained in:
Chris Lattner 2006-08-15 04:50:22 +00:00
parent b8cd5c2260
commit e37e2336b4
2 changed files with 67 additions and 13 deletions

View File

@ -163,6 +163,7 @@ void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
/// specifier-qualifier-list: /// specifier-qualifier-list:
/// type-specifier specifier-qualifier-list[opt] /// type-specifier specifier-qualifier-list[opt]
/// type-qualifier specifier-qualifier-list[opt] /// type-qualifier specifier-qualifier-list[opt]
/// [GNU] attributes specifier-qualifier-list[opt]
/// ///
void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
/// specifier-qualifier-list is a subset of declaration-specifiers. Just /// specifier-qualifier-list is a subset of declaration-specifiers. Just
@ -193,7 +194,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
/// type-specifier declaration-specifiers[opt] /// type-specifier declaration-specifiers[opt]
/// type-qualifier declaration-specifiers[opt] /// type-qualifier declaration-specifiers[opt]
/// [C99] function-specifier declaration-specifiers[opt] /// [C99] function-specifier declaration-specifiers[opt]
/// [GNU] attributes declaration-specifiers[opt] [TODO] /// [GNU] attributes declaration-specifiers[opt]
/// ///
/// storage-class-specifier: [C99 6.7.1] /// storage-class-specifier: [C99 6.7.1]
/// 'typedef' /// 'typedef'
@ -254,6 +255,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
// specifiers. First verify that DeclSpec's are consistent. // specifiers. First verify that DeclSpec's are consistent.
DS.Finish(StartLoc, Diags, getLang()); DS.Finish(StartLoc, Diags, getLang());
return; return;
// GNU attributes support.
case tok::kw___attribute:
ParseAttributes();
break;
// storage-class-specifier // storage-class-specifier
case tok::kw_typedef: case tok::kw_typedef:
@ -376,6 +382,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
/// struct-or-union-specifier: [C99 6.7.2.1] /// struct-or-union-specifier: [C99 6.7.2.1]
/// struct-or-union identifier[opt] '{' struct-contents '}' /// struct-or-union identifier[opt] '{' struct-contents '}'
/// struct-or-union identifier /// struct-or-union identifier
/// [GNU] struct-or-union attributes[opt] identifier[opt] '{' struct-contents
/// '}' attributes[opt]
/// [GNU] struct-or-union attributes[opt] identifier
/// struct-or-union: /// struct-or-union:
/// 'struct' /// 'struct'
/// 'union' /// 'union'
@ -394,9 +403,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
/// struct-declarator-list: /// struct-declarator-list:
/// struct-declarator /// struct-declarator
/// struct-declarator-list ',' struct-declarator /// struct-declarator-list ',' struct-declarator
/// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
/// struct-declarator: /// struct-declarator:
/// declarator /// declarator
/// [GNU] declarator attributes[opt]
/// declarator[opt] ':' constant-expression /// declarator[opt] ':' constant-expression
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
/// ///
void Parser::ParseStructUnionSpecifier(DeclSpec &DS) { void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
assert((Tok.getKind() == tok::kw_struct || assert((Tok.getKind() == tok::kw_struct ||
@ -404,7 +416,11 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
SourceLocation Start = Tok.getLocation(); SourceLocation Start = Tok.getLocation();
bool isUnion = Tok.getKind() == tok::kw_union; bool isUnion = Tok.getKind() == tok::kw_union;
ConsumeToken(); ConsumeToken();
// If attributes exist after tag, parse them.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
// Must have either 'struct name' or 'struct {...}'. // Must have either 'struct name' or 'struct {...}'.
if (Tok.getKind() != tok::identifier && if (Tok.getKind() != tok::identifier &&
Tok.getKind() != tok::l_brace) { Tok.getKind() != tok::l_brace) {
@ -455,6 +471,10 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
// Process it. // Process it.
} }
} }
// If attributes exist after the declarator, parse them.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
// TODO: install declarator. // TODO: install declarator.
@ -468,6 +488,10 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
// Parse the next declarator. // Parse the next declarator.
DeclaratorInfo.clear(); DeclaratorInfo.clear();
// Attributes are only allowed on the second declarator.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
} }
} }
@ -481,6 +505,10 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
} }
MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",diag::err_expected_rbrace); MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",diag::err_expected_rbrace);
// If attributes exist after struct contents, parse them.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
} }
const char *PrevSpec = 0; const char *PrevSpec = 0;
@ -494,9 +522,10 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
/// enum-specifier: [C99 6.7.2.2] /// enum-specifier: [C99 6.7.2.2]
/// 'enum' identifier[opt] '{' enumerator-list '}' /// 'enum' identifier[opt] '{' enumerator-list '}'
/// [C99] 'enum' identifier[opt] '{' enumerator-list ',' '}' /// [C99] 'enum' identifier[opt] '{' enumerator-list ',' '}'
/// [GNU] 'enum' identifier[opt] '{' enumerator-list '}' attributes [TODO] /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
/// [GNU] 'enum' identifier[opt] '{' enumerator-list ',' '}' attributes [TODO] /// '}' attributes[opt]
/// 'enum' identifier /// 'enum' identifier
/// [GNU] 'enum' attributes[opt] identifier
/// enumerator-list: /// enumerator-list:
/// enumerator /// enumerator
/// enumerator-list ',' enumerator /// enumerator-list ',' enumerator
@ -511,6 +540,9 @@ void Parser::ParseEnumSpecifier(DeclSpec &DS) {
SourceLocation Start = Tok.getLocation(); SourceLocation Start = Tok.getLocation();
ConsumeToken(); ConsumeToken();
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
// Must have either 'enum name' or 'enum {...}'. // Must have either 'enum name' or 'enum {...}'.
if (Tok.getKind() != tok::identifier && if (Tok.getKind() != tok::identifier &&
Tok.getKind() != tok::l_brace) { Tok.getKind() != tok::l_brace) {
@ -550,6 +582,10 @@ void Parser::ParseEnumSpecifier(DeclSpec &DS) {
// Eat the }. // Eat the }.
MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{", MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",
diag::err_expected_rbrace); diag::err_expected_rbrace);
// If attributes exist after the identifier list, parse them.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
} }
// TODO: semantic analysis on the declspec for enums. // TODO: semantic analysis on the declspec for enums.
@ -565,6 +601,8 @@ void Parser::ParseEnumSpecifier(DeclSpec &DS) {
bool Parser::isTypeSpecifierQualifier() const { bool Parser::isTypeSpecifierQualifier() const {
switch (Tok.getKind()) { switch (Tok.getKind()) {
default: return false; default: return false;
// GNU attributes support.
case tok::kw___attribute:
// type-specifiers // type-specifiers
case tok::kw_short: case tok::kw_short:
case tok::kw_long: case tok::kw_long:
@ -658,9 +696,9 @@ bool Parser::isDeclarationSpecifier() const {
/// ParseTypeQualifierListOpt /// ParseTypeQualifierListOpt
/// type-qualifier-list: [C99 6.7.5] /// type-qualifier-list: [C99 6.7.5]
/// type-qualifier /// type-qualifier
/// [GNU] attributes [TODO] /// [GNU] attributes
/// type-qualifier-list type-qualifier /// type-qualifier-list type-qualifier
/// [GNU] type-qualifier-list attributes [TODO] /// [GNU] type-qualifier-list attributes
/// ///
void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) { void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
SourceLocation StartLoc = Tok.getLocation(); SourceLocation StartLoc = Tok.getLocation();
@ -670,11 +708,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
switch (Tok.getKind()) { switch (Tok.getKind()) {
default: default:
// If this is not a declaration specifier token, we're done reading decl // If this is not a type-qualifier token, we're done reading type
// specifiers. First verify that DeclSpec's are consistent. // qualifiers. First verify that DeclSpec's are consistent.
DS.Finish(StartLoc, Diags, getLang()); DS.Finish(StartLoc, Diags, getLang());
return; return;
// TODO: attributes.
case tok::kw_const: case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2; isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , PrevSpec, getLang())*2;
break; break;
@ -684,6 +721,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS) {
case tok::kw_restrict: case tok::kw_restrict:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2; isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
break; break;
case tok::kw___attribute:
ParseAttributes();
break;
} }
// If the specifier combination wasn't legal, issue a diagnostic. // If the specifier combination wasn't legal, issue a diagnostic.
@ -759,7 +800,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
ConsumeToken(); ConsumeToken();
} else if (Tok.getKind() == tok::l_paren) { } else if (Tok.getKind() == tok::l_paren) {
// direct-declarator: '(' declarator ')' // direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')' [TODO] // direct-declarator: '(' attributes declarator ')'
// Example: 'char (*X)' or 'int (*XX)(void)' // Example: 'char (*X)' or 'int (*XX)(void)'
ParseParenDeclarator(D); ParseParenDeclarator(D);
} else if (D.mayOmitIdentifier()) { } else if (D.mayOmitIdentifier()) {
@ -802,9 +843,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
/// ///
/// parameter-declaration: [C99 6.7.5] /// parameter-declaration: [C99 6.7.5]
/// declaration-specifiers declarator /// declaration-specifiers declarator
/// [GNU] declaration-specifiers declarator attributes [TODO] /// [GNU] declaration-specifiers declarator attributes
/// declaration-specifiers abstract-declarator[opt] /// declaration-specifiers abstract-declarator[opt]
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes [TODO] /// [GNU] declaration-specifiers abstract-declarator[opt] attributes
/// ///
/// identifier-list: [C99 6.7.5] /// identifier-list: [C99 6.7.5]
/// identifier /// identifier
@ -838,8 +879,11 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// If this is a grouping paren, handle: // If this is a grouping paren, handle:
// direct-declarator: '(' declarator ')' // direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')' [TODO] // direct-declarator: '(' attributes declarator ')'
if (isGrouping) { if (isGrouping) {
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
ParseDeclaratorInternal(D); ParseDeclaratorInternal(D);
// Match the ')'. // Match the ')'.
MatchRHSPunctuation(tok::r_paren, StartLoc, "(", MatchRHSPunctuation(tok::r_paren, StartLoc, "(",
@ -930,6 +974,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
Declarator DeclaratorInfo(DS, Declarator::PrototypeContext); Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
ParseDeclarator(DeclaratorInfo); ParseDeclarator(DeclaratorInfo);
// Parse GNU attributes, if present.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
// TODO: do something with the declarator, if it is valid. // TODO: do something with the declarator, if it is valid.
// If the next token is a comma, consume it and keep reading arguments. // If the next token is a comma, consume it and keep reading arguments.

View File

@ -178,6 +178,7 @@ ParseNextStatement:
/// ///
/// labeled-statement: /// labeled-statement:
/// identifier ':' statement /// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
/// declaration (if !OnlyStatement) /// declaration (if !OnlyStatement)
/// expression[opt] ';' /// expression[opt] ';'
/// ///
@ -191,6 +192,11 @@ void Parser::ParseIdentifierStatement(bool OnlyStatement) {
// identifier ':' statement // identifier ':' statement
if (Tok.getKind() == tok::colon) { if (Tok.getKind() == tok::colon) {
ConsumeToken(); ConsumeToken();
// Read label attributes, if present.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
ParseStatement(); ParseStatement();
return; return;
} }