Switch ParseStructDeclaration to a callback-based API. This will make

it easier to track within Sema whether the parser is parsing a declaration.

llvm-svn: 85855
This commit is contained in:
John McCall 2009-11-03 02:38:08 +00:00
parent 616798c31f
commit cfefb6d197
3 changed files with 131 additions and 90 deletions

View File

@ -979,8 +979,12 @@ private:
void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl); DeclPtrTy TagDecl);
void ParseStructDeclaration(DeclSpec &DS,
llvm::SmallVectorImpl<FieldDeclarator> &Fields); struct FieldCallback {
virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
};
void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
bool isDeclarationSpecifier(); bool isDeclarationSpecifier();
bool isTypeSpecifierQualifier(); bool isTypeSpecifierQualifier();

View File

@ -1468,8 +1468,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
/// [GNU] declarator[opt] ':' constant-expression attributes[opt] /// [GNU] declarator[opt] ':' constant-expression attributes[opt]
/// ///
void Parser:: void Parser::
ParseStructDeclaration(DeclSpec &DS, ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
llvm::SmallVectorImpl<FieldDeclarator> &Fields) {
if (Tok.is(tok::kw___extension__)) { if (Tok.is(tok::kw___extension__)) {
// __extension__ silences extension warnings in the subexpression. // __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this. ExtensionRAIIObject O(Diags); // Use RAII to do this.
@ -1489,9 +1488,16 @@ ParseStructDeclaration(DeclSpec &DS,
} }
// Read struct-declarators until we find the semicolon. // Read struct-declarators until we find the semicolon.
Fields.push_back(FieldDeclarator(DS)); bool FirstDeclarator = true;
while (1) { 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
/// struct-declarator: declarator[opt] ':' constant-expression /// struct-declarator: declarator[opt] ':' constant-expression
@ -1514,6 +1520,9 @@ ParseStructDeclaration(DeclSpec &DS,
DeclaratorInfo.D.AddAttributes(AttrList, Loc); 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 ';') // If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out. // or an error, bail out.
if (Tok.isNot(tok::comma)) if (Tok.isNot(tok::comma))
@ -1522,15 +1531,7 @@ ParseStructDeclaration(DeclSpec &DS,
// Consume the comma. // Consume the comma.
ConsumeToken(); ConsumeToken();
// Parse the next declarator. FirstDeclarator = false;
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);
}
} }
} }
@ -1562,7 +1563,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
<< DeclSpec::getSpecifierName((DeclSpec::TST)TagType); << DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
llvm::SmallVector<DeclPtrTy, 32> FieldDecls; llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
// While we still have something to read, read the declarations in the struct. // While we still have something to read, read the declarations in the struct.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { 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. // Parse all the comma separated declarators.
DeclSpec DS; DeclSpec DS;
FieldDeclarators.clear();
if (!Tok.is(tok::at)) {
ParseStructDeclaration(DS, FieldDeclarators);
// Convert them all to fields. if (!Tok.is(tok::at)) {
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { struct CFieldCallback : FieldCallback {
FieldDeclarator &FD = FieldDeclarators[i]; Parser &P;
DeclPtrTy Field; DeclPtrTy TagDecl;
// Install the declarator into the current TagDecl. llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
if (FD.D.getExtension()) {
// Silences extension warnings CFieldCallback(Parser &P, DeclPtrTy TagDecl,
ExtensionRAIIObject O(Diags); llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
Field = Actions.ActOnField(CurScope, TagDecl, P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
DS.getSourceRange().getBegin(),
FD.D, FD.BitfieldSize); virtual DeclPtrTy invoke(FieldDeclarator &FD) {
} else { const DeclSpec &DS = FD.D.getDeclSpec();
Field = Actions.ActOnField(CurScope, TagDecl, DeclPtrTy Field;
DS.getSourceRange().getBegin(),
FD.D, FD.BitfieldSize); // 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 } else { // Handle @defs
ConsumeToken(); ConsumeToken();
if (!Tok.isObjCAtKeyword(tok::objc_defs)) { if (!Tok.isObjCAtKeyword(tok::objc_defs)) {

View File

@ -305,51 +305,68 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
if (Tok.is(tok::l_paren)) if (Tok.is(tok::l_paren))
ParseObjCPropertyAttribute(OCDS); ParseObjCPropertyAttribute(OCDS);
struct ObjCPropertyCallback : FieldCallback {
Parser &P;
DeclPtrTy IDecl;
llvm::SmallVectorImpl<DeclPtrTy> &Props;
ObjCDeclSpec &OCDS;
SourceLocation AtLoc;
tok::ObjCKeywordKind MethodImplKind;
ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
llvm::SmallVectorImpl<DeclPtrTy> &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. // Parse all the comma separated declarators.
DeclSpec DS; DeclSpec DS;
llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators; ParseStructDeclaration(DS, Callback);
ParseStructDeclaration(DS, FieldDeclarators);
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
tok::at); 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; break;
} }
} }
@ -858,7 +875,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
SourceLocation atLoc) { SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {"); assert(Tok.is(tok::l_brace) && "expected {");
llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls; llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); 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<DeclPtrTy> &AllIvarDecls;
ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
llvm::SmallVectorImpl<DeclPtrTy> &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. // Parse all the comma separated declarators.
DeclSpec DS; DeclSpec DS;
FieldDeclarators.clear(); ParseStructDeclaration(DS, Callback);
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);
}
if (Tok.is(tok::semi)) { if (Tok.is(tok::semi)) {
ConsumeToken(); ConsumeToken();