From: John McCall Date: Tue, 3 Nov 2009 02:38:08 +0000 (+0000) Subject: Switch ParseStructDeclaration to a callback-based API. This will make X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bdd563ec391b0a83fc6d04b8a8ea3022aa702f74;p=clang Switch ParseStructDeclaration to a callback-based API. This will make it easier to track within Sema whether the parser is parsing a declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85855 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 239d68a1ba..fa617ceb7b 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -979,8 +979,12 @@ private: void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); - void ParseStructDeclaration(DeclSpec &DS, - llvm::SmallVectorImpl &Fields); + + struct FieldCallback { + virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0; + }; + + void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback); bool isDeclarationSpecifier(); bool isTypeSpecifierQualifier(); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 55970c0c8c..6cee0b4bb6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1468,8 +1468,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, /// [GNU] declarator[opt] ':' constant-expression attributes[opt] /// void Parser:: -ParseStructDeclaration(DeclSpec &DS, - llvm::SmallVectorImpl &Fields) { +ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -1489,9 +1488,16 @@ ParseStructDeclaration(DeclSpec &DS, } // Read struct-declarators until we find the semicolon. - Fields.push_back(FieldDeclarator(DS)); + bool FirstDeclarator = true; while (1) { - FieldDeclarator &DeclaratorInfo = Fields.back(); + FieldDeclarator DeclaratorInfo(DS); + + // Attributes are only allowed here on successive declarators. + if (!FirstDeclarator && Tok.is(tok::kw___attribute)) { + SourceLocation Loc; + AttributeList *AttrList = ParseAttributes(&Loc); + DeclaratorInfo.D.AddAttributes(AttrList, Loc); + } /// struct-declarator: declarator /// struct-declarator: declarator[opt] ':' constant-expression @@ -1514,6 +1520,9 @@ ParseStructDeclaration(DeclSpec &DS, DeclaratorInfo.D.AddAttributes(AttrList, Loc); } + // We're done with this declarator; invoke the callback. + (void) Fields.invoke(DeclaratorInfo); + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. if (Tok.isNot(tok::comma)) @@ -1522,15 +1531,7 @@ ParseStructDeclaration(DeclSpec &DS, // Consume the comma. ConsumeToken(); - // Parse the next declarator. - Fields.push_back(FieldDeclarator(DS)); - - // Attributes are only allowed on the second declarator. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseAttributes(&Loc); - Fields.back().D.AddAttributes(AttrList, Loc); - } + FirstDeclarator = false; } } @@ -1562,7 +1563,6 @@ 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)) { @@ -1578,28 +1578,39 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // Parse all the comma separated declarators. DeclSpec DS; - FieldDeclarators.clear(); + if (!Tok.is(tok::at)) { - ParseStructDeclaration(DS, FieldDeclarators); - - // Convert them all to fields. - for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { - FieldDeclarator &FD = FieldDeclarators[i]; - DeclPtrTy Field; - // Install the declarator into the current TagDecl. - if (FD.D.getExtension()) { - // Silences extension warnings - ExtensionRAIIObject O(Diags); - Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); - } else { - Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); + struct CFieldCallback : FieldCallback { + Parser &P; + DeclPtrTy TagDecl; + llvm::SmallVectorImpl &FieldDecls; + + CFieldCallback(Parser &P, DeclPtrTy TagDecl, + llvm::SmallVectorImpl &FieldDecls) : + P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {} + + virtual DeclPtrTy invoke(FieldDeclarator &FD) { + const DeclSpec &DS = FD.D.getDeclSpec(); + DeclPtrTy Field; + + // Install the declarator into the current TagDecl. + if (FD.D.getExtension()) { + // Silences extension warnings + ExtensionRAIIObject O(P.Diags); + Field = P.Actions.ActOnField(P.CurScope, TagDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + } else { + Field = P.Actions.ActOnField(P.CurScope, TagDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + } + FieldDecls.push_back(Field); + return Field; } - FieldDecls.push_back(Field); - } + } Callback(*this, TagDecl, FieldDecls); + + ParseStructDeclaration(DS, Callback); } else { // Handle @defs ConsumeToken(); if (!Tok.isObjCAtKeyword(tok::objc_defs)) { diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 2e0cd6d0d9..65d71ae481 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -305,51 +305,68 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, if (Tok.is(tok::l_paren)) ParseObjCPropertyAttribute(OCDS); + struct ObjCPropertyCallback : FieldCallback { + Parser &P; + DeclPtrTy IDecl; + llvm::SmallVectorImpl &Props; + ObjCDeclSpec &OCDS; + SourceLocation AtLoc; + tok::ObjCKeywordKind MethodImplKind; + + ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl, + llvm::SmallVectorImpl &Props, + ObjCDeclSpec &OCDS, SourceLocation AtLoc, + tok::ObjCKeywordKind MethodImplKind) : + P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc), + MethodImplKind(MethodImplKind) { + } + + DeclPtrTy invoke(FieldDeclarator &FD) { + if (FD.D.getIdentifier() == 0) { + P.Diag(AtLoc, diag::err_objc_property_requires_field_name) + << FD.D.getSourceRange(); + return DeclPtrTy(); + } + if (FD.BitfieldSize) { + P.Diag(AtLoc, diag::err_objc_property_bitfield) + << FD.D.getSourceRange(); + return DeclPtrTy(); + } + + // Install the property declarator into interfaceDecl. + IdentifierInfo *SelName = + OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); + + Selector GetterSel = + P.PP.getSelectorTable().getNullarySelector(SelName); + IdentifierInfo *SetterName = OCDS.getSetterName(); + Selector SetterSel; + if (SetterName) + SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName); + else + SetterSel = SelectorTable::constructSetterName(P.PP.getIdentifierTable(), + P.PP.getSelectorTable(), + FD.D.getIdentifier()); + bool isOverridingProperty = false; + DeclPtrTy Property = + P.Actions.ActOnProperty(P.CurScope, AtLoc, FD, OCDS, + GetterSel, SetterSel, IDecl, + &isOverridingProperty, + MethodImplKind); + if (!isOverridingProperty) + Props.push_back(Property); + + return Property; + } + } Callback(*this, interfaceDecl, allProperties, + OCDS, AtLoc, MethodImplKind); + // Parse all the comma separated declarators. DeclSpec DS; - llvm::SmallVector FieldDeclarators; - ParseStructDeclaration(DS, FieldDeclarators); + ParseStructDeclaration(DS, Callback); ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", tok::at); - - // Convert them all to property declarations. - for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { - FieldDeclarator &FD = FieldDeclarators[i]; - if (FD.D.getIdentifier() == 0) { - Diag(AtLoc, diag::err_objc_property_requires_field_name) - << FD.D.getSourceRange(); - continue; - } - if (FD.BitfieldSize) { - Diag(AtLoc, diag::err_objc_property_bitfield) - << FD.D.getSourceRange(); - continue; - } - - // Install the property declarator into interfaceDecl. - IdentifierInfo *SelName = - OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); - - Selector GetterSel = - PP.getSelectorTable().getNullarySelector(SelName); - IdentifierInfo *SetterName = OCDS.getSetterName(); - Selector SetterSel; - if (SetterName) - SetterSel = PP.getSelectorTable().getSelector(1, &SetterName); - else - SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), - FD.D.getIdentifier()); - bool isOverridingProperty = false; - DeclPtrTy Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS, - GetterSel, SetterSel, - interfaceDecl, - &isOverridingProperty, - MethodImplKind); - if (!isOverridingProperty) - allProperties.push_back(Property); - } break; } } @@ -858,7 +875,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); llvm::SmallVector AllIvarDecls; - llvm::SmallVector FieldDeclarators; ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); @@ -893,21 +909,31 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, } } + struct ObjCIvarCallback : FieldCallback { + Parser &P; + DeclPtrTy IDecl; + tok::ObjCKeywordKind visibility; + llvm::SmallVectorImpl &AllIvarDecls; + + ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V, + llvm::SmallVectorImpl &AllIvarDecls) : + P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { + } + + DeclPtrTy invoke(FieldDeclarator &FD) { + // Install the declarator into the interface decl. + DeclPtrTy Field + = P.Actions.ActOnIvar(P.CurScope, + FD.D.getDeclSpec().getSourceRange().getBegin(), + IDecl, FD.D, FD.BitfieldSize, visibility); + AllIvarDecls.push_back(Field); + return Field; + } + } Callback(*this, interfaceDecl, visibility, AllIvarDecls); + // 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. - DeclPtrTy Field = Actions.ActOnIvar(CurScope, - DS.getSourceRange().getBegin(), - interfaceDecl, - FD.D, FD.BitfieldSize, visibility); - AllIvarDecls.push_back(Field); - } + ParseStructDeclaration(DS, Callback); if (Tok.is(tok::semi)) { ConsumeToken();