From 4c172c63e510647e34110c4d5fc23c71c1905b96 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 22 Feb 2010 23:04:20 +0000 Subject: [PATCH] Early support for declaring ivars in class extensions. wip. llvm-svn: 96819 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/include/clang/Parse/Parser.h | 1 + clang/lib/Parse/ParseObjc.cpp | 12 ++++++++---- clang/lib/Sema/SemaDecl.cpp | 13 +++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7c75f2fc7bf3..919397b52c00 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1490,6 +1490,8 @@ def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; +def err_misplaced_ivar : Error<"ivar may be placed in a class extension " + "in non-fragile-abi2 mode only">; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d21fc1f59f4e..a29e47f1ab16 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -849,6 +849,7 @@ private: DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, AttributeList *prefixAttrs = 0); void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind visibility, SourceLocation atLoc); bool ParseObjCProtocolReferences(llvm::SmallVectorImpl &P, llvm::SmallVectorImpl &PLocs, diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 4bf183c4c0eb..7ab0e71dc235 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -188,7 +188,10 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc); - + if (Tok.is(tok::l_brace)) + ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, + atLoc); + ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); return CategoryType; } @@ -229,7 +232,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( EndProtoLoc, attrList); if (Tok.is(tok::l_brace)) - ParseObjCClassInstanceVariables(ClsType, atLoc); + ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc); ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); return ClsType; @@ -965,6 +968,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl &Protocols, /// struct-declaration /// void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind visibility, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); llvm::SmallVector AllIvarDecls; @@ -973,7 +977,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, SourceLocation LBraceLoc = ConsumeBrace(); // the "{" - tok::ObjCKeywordKind visibility = tok::objc_protected; // While we still have something to read, read the instance variables. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one objc-instance-variable-decl. @@ -1228,7 +1231,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( superClassId, superClassLoc); if (Tok.is(tok::l_brace)) // we have ivars - ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc); + ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, + tok::objc_protected, atLoc); ObjCImpDecl = ImplClsType; PendingObjCImpDecl.push_back(ObjCImpDecl); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c59e8bad6678..0be3841ad5a8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5682,6 +5682,19 @@ void Sema::ActOnFields(Scope* S, // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + } else if (ObjCCategoryDecl *CDecl = + dyn_cast(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) + Diag(LBrac, diag::err_misplaced_ivar); + else { + // FIXME. Class extension does not have a LocEnd field. + // CDecl->setLocEnd(RBrac); + // Add ivar's to class extension's DeclContext. + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + ClsFields[i]->setLexicalDeclContext(CDecl); + CDecl->addDecl(ClsFields[i]); + } + } } }