refactor Parser::ParseStructDeclaration to return a vector of uninterpreted
declarators. This allows the clients (C structs, objc classes, objc properties, [future] C++ classes) etc, to do custom processing before invoking an action. This has two benefits in the short term: 1) objc ivar processing should be split out of ActOnField into its own ActOn method. 2) the new objc ivar action can take visibility info directly, eliminating AllVisibilities in ParseObjCClassInstanceVariables. 3) objc properties can pass their own special sauce down to sema as well. llvm-svn: 49468
This commit is contained in:
parent
32295d344a
commit
a12405b0ef
|
@ -665,6 +665,17 @@ public:
|
||||||
bool getInvalidType() const { return InvalidType; }
|
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
|
} // end namespace clang
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace clang {
|
||||||
class DeclSpec;
|
class DeclSpec;
|
||||||
class ObjCDeclSpec;
|
class ObjCDeclSpec;
|
||||||
class Declarator;
|
class Declarator;
|
||||||
|
class FieldDeclarator;
|
||||||
class AttributeList;
|
class AttributeList;
|
||||||
class Scope;
|
class Scope;
|
||||||
|
|
||||||
|
@ -453,8 +454,8 @@ private:
|
||||||
void ParseStructUnionSpecifier(DeclSpec &DS);
|
void ParseStructUnionSpecifier(DeclSpec &DS);
|
||||||
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
|
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
|
||||||
DeclTy *TagDecl);
|
DeclTy *TagDecl);
|
||||||
void ParseStructDeclaration(DeclTy *TagDecl,
|
void ParseStructDeclaration(DeclSpec &DS,
|
||||||
llvm::SmallVectorImpl<DeclTy*> &FieldDecls);
|
llvm::SmallVectorImpl<FieldDeclarator> &Fields);
|
||||||
|
|
||||||
bool isDeclarationSpecifier() const;
|
bool isDeclarationSpecifier() const;
|
||||||
bool isTypeSpecifierQualifier() const;
|
bool isTypeSpecifierQualifier() const;
|
||||||
|
|
|
@ -657,14 +657,14 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
|
||||||
/// declarator[opt] ':' constant-expression
|
/// declarator[opt] ':' constant-expression
|
||||||
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
|
/// [GNU] declarator[opt] ':' constant-expression attributes[opt]
|
||||||
///
|
///
|
||||||
void Parser::ParseStructDeclaration(DeclTy *TagDecl,
|
void Parser::
|
||||||
llvm::SmallVectorImpl<DeclTy*> &FieldDecls) {
|
ParseStructDeclaration(DeclSpec &DS,
|
||||||
|
llvm::SmallVectorImpl<FieldDeclarator> &Fields) {
|
||||||
// FIXME: When __extension__ is specified, disable extension diagnostics.
|
// FIXME: When __extension__ is specified, disable extension diagnostics.
|
||||||
if (Tok.is(tok::kw___extension__))
|
while (Tok.is(tok::kw___extension__))
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
||||||
// Parse the common specifier-qualifiers-list piece.
|
// Parse the common specifier-qualifiers-list piece.
|
||||||
DeclSpec DS;
|
|
||||||
SourceLocation DSStart = Tok.getLocation();
|
SourceLocation DSStart = Tok.getLocation();
|
||||||
ParseSpecifierQualifierList(DS);
|
ParseSpecifierQualifierList(DS);
|
||||||
// TODO: Does specifier-qualifier list correctly check that *something* is
|
// 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.
|
// Read struct-declarators until we find the semicolon.
|
||||||
Declarator DeclaratorInfo(DS, Declarator::MemberContext);
|
Fields.push_back(DS);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
FieldDeclarator &DeclaratorInfo = Fields.back();
|
||||||
|
|
||||||
/// struct-declarator: declarator
|
/// struct-declarator: declarator
|
||||||
/// struct-declarator: declarator[opt] ':' constant-expression
|
/// struct-declarator: declarator[opt] ':' constant-expression
|
||||||
if (Tok.isNot(tok::colon))
|
if (Tok.isNot(tok::colon))
|
||||||
ParseDeclarator(DeclaratorInfo);
|
ParseDeclarator(DeclaratorInfo.D);
|
||||||
|
|
||||||
ExprTy *BitfieldSize = 0;
|
|
||||||
if (Tok.is(tok::colon)) {
|
if (Tok.is(tok::colon)) {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
ExprResult Res = ParseConstantExpression();
|
ExprResult Res = ParseConstantExpression();
|
||||||
if (Res.isInvalid)
|
if (Res.isInvalid)
|
||||||
SkipUntil(tok::semi, true, true);
|
SkipUntil(tok::semi, true, true);
|
||||||
else
|
else
|
||||||
BitfieldSize = Res.Val;
|
DeclaratorInfo.BitfieldSize = Res.Val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If attributes exist after the declarator, parse them.
|
// If attributes exist after the declarator, parse them.
|
||||||
if (Tok.is(tok::kw___attribute))
|
if (Tok.is(tok::kw___attribute))
|
||||||
DeclaratorInfo.AddAttributes(ParseAttributes());
|
DeclaratorInfo.D.AddAttributes(ParseAttributes());
|
||||||
|
|
||||||
// Install the declarator into the current TagDecl.
|
|
||||||
DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,
|
|
||||||
DS.getSourceRange().getBegin(),
|
|
||||||
DeclaratorInfo, BitfieldSize);
|
|
||||||
FieldDecls.push_back(Field);
|
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -714,11 +708,11 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl,
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
||||||
// Parse the next declarator.
|
// Parse the next declarator.
|
||||||
DeclaratorInfo.clear();
|
Fields.push_back(DS);
|
||||||
|
|
||||||
// Attributes are only allowed on the second declarator.
|
// Attributes are only allowed on the second declarator.
|
||||||
if (Tok.is(tok::kw___attribute))
|
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));
|
DeclSpec::getSpecifierName((DeclSpec::TST)TagType));
|
||||||
|
|
||||||
llvm::SmallVector<DeclTy*, 32> FieldDecls;
|
llvm::SmallVector<DeclTy*, 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)) {
|
||||||
// Each iteration of this loop reads one struct-declaration.
|
// Each iteration of this loop reads one struct-declaration.
|
||||||
|
@ -754,7 +749,22 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
continue;
|
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)) {
|
if (Tok.is(tok::semi)) {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
|
@ -378,16 +378,31 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl,
|
||||||
SourceLocation AtLoc) {
|
SourceLocation AtLoc) {
|
||||||
assert(Tok.isObjCAtKeyword(tok::objc_property) &&
|
assert(Tok.isObjCAtKeyword(tok::objc_property) &&
|
||||||
"ParseObjCPropertyDecl(): Expected @property");
|
"ParseObjCPropertyDecl(): Expected @property");
|
||||||
ObjCDeclSpec DS;
|
ObjCDeclSpec OCDS;
|
||||||
ConsumeToken(); // the "property" identifier
|
ConsumeToken(); // the "property" identifier
|
||||||
// Parse property attribute list, if any.
|
// Parse property attribute list, if any.
|
||||||
if (Tok.is(tok::l_paren)) {
|
if (Tok.is(tok::l_paren)) {
|
||||||
// property has attribute list.
|
// property has attribute list.
|
||||||
ParseObjCPropertyAttribute(DS);
|
ParseObjCPropertyAttribute(OCDS);
|
||||||
}
|
}
|
||||||
// Parse declaration portion of @property.
|
// Parse declaration portion of @property.
|
||||||
llvm::SmallVector<DeclTy*, 8> PropertyDecls;
|
llvm::SmallVector<DeclTy*, 8> PropertyDecls;
|
||||||
ParseStructDeclaration(interfaceDecl, PropertyDecls);
|
|
||||||
|
// Parse all the comma separated declarators.
|
||||||
|
DeclSpec DS;
|
||||||
|
llvm::SmallVector<FieldDeclarator, 8> 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))
|
if (Tok.is(tok::semi))
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
else {
|
else {
|
||||||
|
@ -395,7 +410,7 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl,
|
||||||
SkipUntil(tok::r_brace, true, true);
|
SkipUntil(tok::r_brace, true, true);
|
||||||
}
|
}
|
||||||
return Actions.ActOnAddObjCProperties(AtLoc, &PropertyDecls[0],
|
return Actions.ActOnAddObjCProperties(AtLoc, &PropertyDecls[0],
|
||||||
PropertyDecls.size(), DS);
|
PropertyDecls.size(), OCDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// objc-method-proto:
|
/// objc-method-proto:
|
||||||
|
@ -756,10 +771,10 @@ bool Parser::ParseObjCProtocolReferences(
|
||||||
void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
||||||
SourceLocation atLoc) {
|
SourceLocation atLoc) {
|
||||||
assert(Tok.is(tok::l_brace) && "expected {");
|
assert(Tok.is(tok::l_brace) && "expected {");
|
||||||
llvm::SmallVector<DeclTy*, 16> IvarDecls;
|
|
||||||
llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
|
llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
|
||||||
llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
|
llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
|
||||||
|
llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
|
||||||
|
|
||||||
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
|
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
|
||||||
|
|
||||||
tok::ObjCKeywordKind visibility = tok::objc_private;
|
tok::ObjCKeywordKind visibility = tok::objc_private;
|
||||||
|
@ -773,6 +788,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the default visibility to private.
|
// Set the default visibility to private.
|
||||||
if (Tok.is(tok::at)) { // parse objc-visibility-spec
|
if (Tok.is(tok::at)) { // parse objc-visibility-spec
|
||||||
ConsumeToken(); // eat the @ sign
|
ConsumeToken(); // eat the @ sign
|
||||||
|
@ -786,16 +802,25 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
Diag(Tok, diag::err_objc_illegal_visibility_spec);
|
Diag(Tok, diag::err_objc_illegal_visibility_spec);
|
||||||
ConsumeToken();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParseStructDeclaration(interfaceDecl, IvarDecls);
|
|
||||||
for (unsigned i = 0; i < IvarDecls.size(); i++) {
|
// Parse all the comma separated declarators.
|
||||||
AllIvarDecls.push_back(IvarDecls[i]);
|
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);
|
AllVisibilities.push_back(visibility);
|
||||||
}
|
}
|
||||||
IvarDecls.clear();
|
|
||||||
|
|
||||||
if (Tok.is(tok::semi)) {
|
if (Tok.is(tok::semi)) {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
Loading…
Reference in New Issue