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 ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
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 isTypeSpecifierQualifier();

View File

@ -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<FieldDeclarator> &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<DeclPtrTy, 32> FieldDecls;
llvm::SmallVector<FieldDeclarator, 8> 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);
if (!Tok.is(tok::at)) {
struct CFieldCallback : FieldCallback {
Parser &P;
DeclPtrTy TagDecl;
llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
CFieldCallback(Parser &P, DeclPtrTy TagDecl,
llvm::SmallVectorImpl<DeclPtrTy> &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)) {

View File

@ -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<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.
DeclSpec DS;
llvm::SmallVector<FieldDeclarator, 8> 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<DeclPtrTy, 32> AllIvarDecls;
llvm::SmallVector<FieldDeclarator, 8> 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<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.
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();