diff options
author | Chris Lattner <sabre@nondot.org> | 2008-06-21 19:39:06 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-06-21 19:39:06 +0000 |
commit | 5a6ddbf295d2ea1c28cfb67d82db22f3893ede6f (patch) | |
tree | c7568aa7f57f05d9e0744bff2440f663c0566f34 /lib | |
parent | 63e9d5673791096589c601528e857e00a13050ff (diff) |
add parser and sema support for the funny ObjC '@defs' thing.
Patch by David Chisnall!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52586 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 47 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 29 |
3 files changed, 65 insertions, 13 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 46246e64ba..95344c438e 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -707,7 +707,7 @@ ParseStructDeclaration(DeclSpec &DS, /// struct-declaration-list: /// struct-declaration /// struct-declaration-list struct-declaration -/// [OBC] '@' 'defs' '(' class-name ')' [TODO] +/// [OBC] '@' 'defs' '(' class-name ')' /// void Parser::ParseStructUnionBody(SourceLocation RecordLoc, unsigned TagType, DeclTy *TagDecl) { @@ -736,18 +736,39 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // 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, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); - FieldDecls.push_back(Field); - } - + 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]; + // Install the declarator into the current TagDecl. + DeclTy *Field = Actions.ActOnField(CurScope, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + FieldDecls.push_back(Field); + } + } else { // Handle @defs + ConsumeToken(); + if (!Tok.isObjCAtKeyword(tok::objc_defs)) { + Diag(Tok, diag::err_unexpected_at); + SkipUntil(tok::semi, true, true); + continue; + } + ConsumeToken(); + ExpectAndConsume(tok::l_paren, diag::err_expected_lparen); + if (!Tok.is(tok::identifier)) { + Diag(Tok, diag::err_expected_ident); + SkipUntil(tok::semi, true, true); + continue; + } + llvm::SmallVector<DeclTy*, 16> Fields; + Actions.ActOnDefs(CurScope, Tok.getLocation(), Tok.getIdentifierInfo(), + Fields); + FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end()); + ConsumeToken(); + ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); + } if (Tok.is(tok::semi)) { ConsumeToken(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b3b5941dc3..1d68160813 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -240,6 +240,8 @@ private: virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK, SourceLocation KWLoc, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr); + virtual void ActOnDefs(Scope *S, SourceLocation DeclStart, IdentifierInfo + *ClassName, llvm::SmallVector<DeclTy*, 16> &Decls); virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7af557b1a8..ee1aad54ed 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1731,6 +1731,35 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, return New; } +/// Collect the instance variables declared in an Objective-C object. Used in +/// the creation of structures from objects using the @defs directive. +static void CollectIvars(ObjCInterfaceDecl *Class, + llvm::SmallVector<Sema::DeclTy*, 16> &ivars) { + if (Class->getSuperClass()) + CollectIvars(Class->getSuperClass(), ivars); + ivars.append(Class->ivar_begin(), Class->ivar_end()); +} + +/// Called whenever @defs(ClassName) is encountered in the source. Inserts the +/// instance variables of ClassName into Decls. +void Sema::ActOnDefs(Scope *S, SourceLocation DeclStart, + IdentifierInfo *ClassName, + llvm::SmallVector<DeclTy*, 16> &Decls) { + // Check that ClassName is a valid class + ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName); + if (!Class) { + Diag(DeclStart, diag::err_undef_interface, ClassName->getName()); + return; + } + // Add the isa pointer + Decls.push_back(FieldDecl::Create(Context, SourceLocation(), + &Context.Idents.get("isa"), + Context.getObjCClassType())); + // Collect the instance variables + CollectIvars(Class, Decls); +} + + static bool CalcFakeICEVal(const Expr* Expr, llvm::APSInt& Result, ASTContext& Context) { |