diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index 6204a383b9a3..b0efc188ef43 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -665,6 +665,17 @@ public: bool getInvalidType() const { return InvalidType; } }; +/// FieldDeclarator - This little struct is used to capture information about +/// structure field declarators, which is basically just a bitfield size. +struct FieldDeclarator { + Declarator D; + Action::ExprTy *BitfieldSize; + FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { + BitfieldSize = 0; + } +}; + + } // end namespace clang #endif diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a45f81a246ac..13535805e244 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -21,6 +21,7 @@ namespace clang { class DeclSpec; class ObjCDeclSpec; class Declarator; + class FieldDeclarator; class AttributeList; class Scope; @@ -453,8 +454,8 @@ private: void ParseStructUnionSpecifier(DeclSpec &DS); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, DeclTy *TagDecl); - void ParseStructDeclaration(DeclTy *TagDecl, - llvm::SmallVectorImpl &FieldDecls); + void ParseStructDeclaration(DeclSpec &DS, + llvm::SmallVectorImpl &Fields); bool isDeclarationSpecifier() const; bool isTypeSpecifierQualifier() const; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 77287043a53c..1d412482ea90 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -657,14 +657,14 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) { /// declarator[opt] ':' constant-expression /// [GNU] declarator[opt] ':' constant-expression attributes[opt] /// -void Parser::ParseStructDeclaration(DeclTy *TagDecl, - llvm::SmallVectorImpl &FieldDecls) { +void Parser:: +ParseStructDeclaration(DeclSpec &DS, + llvm::SmallVectorImpl &Fields) { // FIXME: When __extension__ is specified, disable extension diagnostics. - if (Tok.is(tok::kw___extension__)) + while (Tok.is(tok::kw___extension__)) ConsumeToken(); // Parse the common specifier-qualifiers-list piece. - DeclSpec DS; SourceLocation DSStart = Tok.getLocation(); ParseSpecifierQualifierList(DS); // TODO: Does specifier-qualifier list correctly check that *something* is @@ -677,33 +677,27 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl, } // Read struct-declarators until we find the semicolon. - Declarator DeclaratorInfo(DS, Declarator::MemberContext); - + Fields.push_back(DS); while (1) { + FieldDeclarator &DeclaratorInfo = Fields.back(); + /// struct-declarator: declarator /// struct-declarator: declarator[opt] ':' constant-expression if (Tok.isNot(tok::colon)) - ParseDeclarator(DeclaratorInfo); + ParseDeclarator(DeclaratorInfo.D); - ExprTy *BitfieldSize = 0; if (Tok.is(tok::colon)) { ConsumeToken(); ExprResult Res = ParseConstantExpression(); if (Res.isInvalid) SkipUntil(tok::semi, true, true); else - BitfieldSize = Res.Val; + DeclaratorInfo.BitfieldSize = Res.Val; } // If attributes exist after the declarator, parse them. if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.AddAttributes(ParseAttributes()); - - // Install the declarator into the current TagDecl. - DeclTy *Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - DeclaratorInfo, BitfieldSize); - FieldDecls.push_back(Field); + DeclaratorInfo.D.AddAttributes(ParseAttributes()); // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. @@ -714,11 +708,11 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl, ConsumeToken(); // Parse the next declarator. - DeclaratorInfo.clear(); + Fields.push_back(DS); // Attributes are only allowed on the second declarator. if (Tok.is(tok::kw___attribute)) - DeclaratorInfo.AddAttributes(ParseAttributes()); + Fields.back().D.AddAttributes(ParseAttributes()); } } @@ -743,7 +737,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, DeclSpec::getSpecifierName((DeclSpec::TST)TagType)); llvm::SmallVector FieldDecls; - + llvm::SmallVector FieldDeclarators; + // While we still have something to read, read the declarations in the struct. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one struct-declaration. @@ -754,7 +749,22 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, ConsumeToken(); continue; } - ParseStructDeclaration(TagDecl, FieldDecls); + + // Parse all the comma separated declarators. + DeclSpec DS; + FieldDeclarators.clear(); + ParseStructDeclaration(DS, FieldDeclarators); + + // Convert them all to fields. + for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { + FieldDeclarator &FD = FieldDeclarators[i]; + // Install the declarator into the current TagDecl. + DeclTy *Field = Actions.ActOnField(CurScope, TagDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + FieldDecls.push_back(Field); + } + if (Tok.is(tok::semi)) { ConsumeToken(); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 2aee03ae95b6..5a9b980b6dd4 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -378,16 +378,31 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl, SourceLocation AtLoc) { assert(Tok.isObjCAtKeyword(tok::objc_property) && "ParseObjCPropertyDecl(): Expected @property"); - ObjCDeclSpec DS; + ObjCDeclSpec OCDS; ConsumeToken(); // the "property" identifier // Parse property attribute list, if any. if (Tok.is(tok::l_paren)) { // property has attribute list. - ParseObjCPropertyAttribute(DS); + ParseObjCPropertyAttribute(OCDS); } // Parse declaration portion of @property. llvm::SmallVector PropertyDecls; - ParseStructDeclaration(interfaceDecl, PropertyDecls); + + // Parse all the comma separated declarators. + DeclSpec DS; + llvm::SmallVector FieldDeclarators; + ParseStructDeclaration(DS, FieldDeclarators); + + // Convert them all to fields. + for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { + FieldDeclarator &FD = FieldDeclarators[i]; + // Install the declarator into interfaceDecl. + DeclTy *Field = Actions.ActOnField(CurScope, interfaceDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + PropertyDecls.push_back(Field); + } + if (Tok.is(tok::semi)) ConsumeToken(); else { @@ -395,7 +410,7 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl, SkipUntil(tok::r_brace, true, true); } return Actions.ActOnAddObjCProperties(AtLoc, &PropertyDecls[0], - PropertyDecls.size(), DS); + PropertyDecls.size(), OCDS); } /// objc-method-proto: @@ -756,10 +771,10 @@ bool Parser::ParseObjCProtocolReferences( void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); - llvm::SmallVector IvarDecls; llvm::SmallVector AllIvarDecls; llvm::SmallVector AllVisibilities; - + llvm::SmallVector FieldDeclarators; + SourceLocation LBraceLoc = ConsumeBrace(); // the "{" tok::ObjCKeywordKind visibility = tok::objc_private; @@ -773,6 +788,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, ConsumeToken(); continue; } + // Set the default visibility to private. if (Tok.is(tok::at)) { // parse objc-visibility-spec ConsumeToken(); // eat the @ sign @@ -786,16 +802,25 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, continue; default: Diag(Tok, diag::err_objc_illegal_visibility_spec); - ConsumeToken(); continue; } } - ParseStructDeclaration(interfaceDecl, IvarDecls); - for (unsigned i = 0; i < IvarDecls.size(); i++) { - AllIvarDecls.push_back(IvarDecls[i]); + + // Parse all the comma separated declarators. + DeclSpec DS; + FieldDeclarators.clear(); + ParseStructDeclaration(DS, FieldDeclarators); + + // Convert them all to fields. + for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { + FieldDeclarator &FD = FieldDeclarators[i]; + // Install the declarator into interfaceDecl. + DeclTy *Field = Actions.ActOnField(CurScope, interfaceDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + AllIvarDecls.push_back(Field); AllVisibilities.push_back(visibility); } - IvarDecls.clear(); if (Tok.is(tok::semi)) { ConsumeToken();