From: Steve Naroff Date: Thu, 6 Sep 2007 21:24:23 +0000 (+0000) Subject: The goal of this commit is to get just enough Sema support to recognize Objective... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3536b443bc50d58a79f14fca9b6842541a434854;p=clang The goal of this commit is to get just enough Sema support to recognize Objective-C classes as types. That said, the AST nodes ObjcInterfaceDecl, ObjcInterfaceType, and ObjcClassDecl are *very* preliminary. The good news is we no longer need -parse-noop (aka MinimalActions) to parse cocoa.m. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41752 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 8879336b43..7e9f5e96b0 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -596,6 +596,16 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) { return QualType(Decl->TypeForDecl, 0); } +/// getObjcInterfaceType - Return the unique reference to the type for the +/// specified ObjC interface decl. +QualType ASTContext::getObjcInterfaceType(ObjcInterfaceDecl *Decl) { + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + Decl->TypeForDecl = new ObjcInterfaceType(Decl); + Types.push_back(Decl->TypeForDecl); + return QualType(Decl->TypeForDecl, 0); +} + /// getTypeOfExpr - Unlike many "get" functions, we can't unique /// TypeOfExpr AST's (since expression's are never shared). For example, /// multiple declarations that refer to "typeof(x)" all contain different diff --git a/AST/Decl.cpp b/AST/Decl.cpp index f4a346ff97..5f87d93cbb 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -25,6 +25,7 @@ static unsigned nEnumConst = 0; static unsigned nEnumDecls = 0; static unsigned nTypedef = 0; static unsigned nFieldDecls = 0; +static unsigned nInterfaceDecls = 0; static bool StatSwitch = false; bool Decl::CollectingStats(bool enable) { @@ -101,6 +102,9 @@ void Decl::addDeclKind(const Kind k) { case Enum: nEnumDecls++; break; + case ObjcInterface: + nInterfaceDecls++; + break; } } diff --git a/AST/Type.cpp b/AST/Type.cpp index 26bfbe231b..f7779bc3c6 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -836,6 +836,12 @@ void TypedefType::getAsStringInternal(std::string &InnerString) const { InnerString = getDecl()->getIdentifier()->getName() + InnerString; } +void ObjcInterfaceType::getAsStringInternal(std::string &InnerString) const { + if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. + InnerString = ' ' + InnerString; + InnerString = getDecl()->getIdentifier()->getName() + InnerString; +} + void TagType::getAsStringInternal(std::string &InnerString) const { if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. InnerString = ' ' + InnerString; diff --git a/Parse/MinimalAction.cpp b/Parse/MinimalAction.cpp index 65bdca64db..8ca72589ad 100644 --- a/Parse/MinimalAction.cpp +++ b/Parse/MinimalAction.cpp @@ -68,12 +68,24 @@ MinimalAction::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, return 0; } -/// ParsedObjcClassDeclaration - +Action::DeclTy * +MinimalAction::ObjcStartClassInterface(SourceLocation AtInterafceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + IdentifierInfo **ProtocolNames, unsigned NumProtocols, + AttributeList *AttrList) { + TypeNameInfo *TI = + new TypeNameInfo(1, ClassName->getFETokenInfo()); + + ClassName->setFETokenInfo(TI); + return 0; +} + +/// ObjcClassDeclaration - /// Scope will always be top level file scope. Action::DeclTy * -MinimalAction::ParsedObjcClassDeclaration(Scope *S, - IdentifierInfo **IdentList, - unsigned NumElts) { +MinimalAction::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, unsigned NumElts) { for (unsigned i = 0; i != NumElts; ++i) { TypeNameInfo *TI = new TypeNameInfo(1, IdentList[i]->getFETokenInfo()); diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index 39772a3d6a..6557c41652 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -37,7 +37,7 @@ Parser::DeclTy *Parser::ParseObjCAtDirectives() { case tok::objc_protocol: return ParseObjCAtProtocolDeclaration(AtLoc); case tok::objc_implementation: - return ParseObjCAtImplementationDeclaration(AtLoc); + return ObjcImpDecl = ParseObjCAtImplementationDeclaration(AtLoc); case tok::objc_end: return ParseObjCAtEndDeclaration(AtLoc); case tok::objc_compatibility_alias: @@ -80,8 +80,8 @@ Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) return 0; - return Actions.ParsedObjcClassDeclaration(CurScope, - &ClassNames[0], ClassNames.size()); + return Actions.ObjcClassDeclaration(CurScope, atLoc, + &ClassNames[0], ClassNames.size()); } /// @@ -154,8 +154,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( if (attrList) // categories don't support attributes. Diag(Tok, diag::err_objc_no_attributes_on_category); - llvm::SmallVector MethodDecls; - ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls); + ParseObjCInterfaceDeclList(0/*FIXME*/); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -169,11 +168,6 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( IdentifierInfo *superClassId = 0; SourceLocation superClassLoc; - // FIXME: temporary hack to grok class names (until we have sema support). - llvm::SmallVector ClassName; - ClassName.push_back(nameId); - Actions.ParsedObjcClassDeclaration(CurScope, &ClassName[0], 1); - if (Tok.getKind() == tok::colon) { // a super class is specified. ConsumeToken(); if (Tok.getKind() != tok::identifier) { @@ -193,12 +187,10 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( superClassId, superClassLoc, &ProtocolRefs[0], ProtocolRefs.size(), attrList); - llvm::SmallVector IvarDecls; if (Tok.getKind() == tok::l_brace) - ParseObjCClassInstanceVariables(ClsType, IvarDecls); + ParseObjCClassInstanceVariables(ClsType); - llvm::SmallVector MethodDecls; - ParseObjCInterfaceDeclList(ClsType, MethodDecls); + ParseObjCInterfaceDeclList(ClsType); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -213,7 +205,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( /// empty /// objc-interface-decl-list objc-property-decl [OBJC2] /// objc-interface-decl-list objc-method-requirement [OBJC2] -/// objc-interface-decl-list objc-method-proto +/// objc-interface-decl-list objc-method-proto ';' /// objc-interface-decl-list declaration /// objc-interface-decl-list ';' /// @@ -221,9 +213,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( /// @required /// @optional /// -void Parser::ParseObjCInterfaceDeclList( - DeclTy *interfaceDecl, llvm::SmallVectorImpl &MethodDecls) { - DeclTy *IDecl = 0; +void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) { while (1) { if (Tok.getKind() == tok::at) { SourceLocation AtLoc = ConsumeToken(); // the "@" @@ -246,8 +236,10 @@ void Parser::ParseObjCInterfaceDeclList( } } if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) { - IDecl = ParseObjCMethodPrototype(true); - MethodDecls.push_back(IDecl); + ParseObjCMethodPrototype(interfaceDecl); + // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for + // method definitions. + ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto"); continue; } if (Tok.getKind() == tok::semi) @@ -257,8 +249,7 @@ void Parser::ParseObjCInterfaceDeclList( else { // FIXME: as the name implies, this rule allows function definitions. // We could pass a flag or check for functions during semantic analysis. - IDecl = ParseDeclarationOrFunctionDefinition(); - MethodDecls.push_back(IDecl); + ParseDeclarationOrFunctionDefinition(); } } } @@ -355,10 +346,9 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) { } } -/// objc-methodproto: +/// objc-method-proto: /// objc-instance-method objc-method-decl objc-method-attributes[opt] -/// ';'[opt] -/// objc-class-method objc-method-decl objc-method-attributes[opt] ';'[opt] +/// objc-class-method objc-method-decl objc-method-attributes[opt] /// /// objc-instance-method: '-' /// objc-class-method: '+' @@ -366,19 +356,25 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) { /// objc-method-attributes: [OBJC2] /// __attribute__((deprecated)) /// -Parser::DeclTy *Parser::ParseObjCMethodPrototype(bool decl) { +Parser::DeclTy *Parser::ParseObjCMethodPrototype(DeclTy *CDecl) { assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation methodLoc = ConsumeToken(); - // FIXME: deal with "context sensitive" protocol qualifiers in prototypes DeclTy *MDecl = ParseObjCMethodDecl(methodType, methodLoc); + + AttributeList *methodAttrs = 0; + // If attributes exist after the method, parse them. + if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) + methodAttrs = ParseAttributes(); + + if (CDecl) + Actions.ObjcAddMethod(CDecl, MDecl, methodAttrs); - if (decl) - // Consume the ';'. - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto"); + // Since this rule is used for both method declarations and definitions, + // the caller is responsible for consuming the ';'. return MDecl; } @@ -546,24 +542,13 @@ Parser::DeclTy *Parser::ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation Declarator ParmDecl(DS, Declarator::PrototypeContext); ParseDeclarator(ParmDecl); } - AttributeList *methodAttrs = 0; - // If attributes exist after the method, parse them. - if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) - methodAttrs = ParseAttributes(); - // FIXME: Add support for optional parmameter list... return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, - &KeyInfo[0], KeyInfo.size(), - methodAttrs); + &KeyInfo[0], KeyInfo.size()); } else if (!selIdent) { Diag(Tok, diag::err_expected_ident); // missing selector name. } - AttributeList *methodAttrs = 0; - // If attributes exist after the method, parse them. - if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute) - methodAttrs = ParseAttributes(); - return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent, - methodAttrs); + return Actions.ObjcBuildMethodDeclaration(mLoc, mType, ReturnType, selIdent); } /// objc-protocol-refs: @@ -612,9 +597,9 @@ bool Parser::ParseObjCProtocolReferences( /// objc-instance-variable-decl: /// struct-declaration /// -void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, - llvm::SmallVectorImpl &IvarDecls) { +void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) { assert(Tok.getKind() == tok::l_brace && "expected {"); + llvm::SmallVector IvarDecls; SourceLocation LBraceLoc = ConsumeBrace(); // the "{" @@ -648,7 +633,10 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, } } ParseStructDeclaration(interfaceDecl, IvarDecls); - + for (unsigned i = 0; i < IvarDecls.size(); i++) + Actions.ObjcAddInstanceVariable(interfaceDecl, IvarDecls[i], visibility); + IvarDecls.clear(); + if (Tok.getKind() == tok::semi) { ConsumeToken(); } else if (Tok.getKind() == tok::r_brace) { @@ -671,14 +659,14 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, /// objc-protocol-definition: /// @protocol identifier /// objc-protocol-refs[opt] -/// objc-methodprotolist +/// objc-interface-decl-list /// @end /// /// objc-protocol-forward-reference: /// @protocol identifier-list ';' /// /// "@protocol identifier ;" should be resolved as "@protocol -/// identifier-list ;": objc-methodprotolist may not start with a +/// identifier-list ;": objc-interface-decl-list may not start with a /// semicolon in the first alternative if objc-protocol-refs are omitted. Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) { @@ -727,8 +715,7 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) { if (ParseObjCProtocolReferences(ProtocolRefs)) return 0; } - llvm::SmallVector MethodDecls; - ParseObjCInterfaceDeclList(0/*FIXME*/, MethodDecls); + ParseObjCInterfaceDeclList(0/*FIXME*/); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). if (Tok.isObjCAtKeyword(tok::objc_end)) { @@ -794,9 +781,8 @@ Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration( } ConsumeToken(); // Consume super class name } - llvm::SmallVector IvarDecls; if (Tok.getKind() == tok::l_brace) - ParseObjCClassInstanceVariables(0/*FIXME*/, IvarDecls); // we have ivars + ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars return 0; } @@ -895,12 +881,12 @@ Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { return 0; } -/// objc-method-def: objc-methodproto ';'[opt] '{' body '}' +/// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// void Parser::ParseObjCInstanceMethodDefinition() { assert(Tok.getKind() == tok::minus && "ParseObjCInstanceMethodDefinition(): Expected '-'"); - ParseObjCMethodPrototype(false); + ParseObjCMethodPrototype(ObjcImpDecl); // parse optional ';' if (Tok.getKind() == tok::semi) ConsumeToken(); @@ -913,12 +899,12 @@ void Parser::ParseObjCInstanceMethodDefinition() { StmtResult FnBody = ParseCompoundStatementBody(); } -/// objc-method-def: objc-methodproto ';'[opt] '{' body '}' +/// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// void Parser::ParseObjCClassMethodDefinition() { assert(Tok.getKind() == tok::plus && "ParseObjCClassMethodDefinition(): Expected '+'"); - ParseObjCMethodPrototype(false); + ParseObjCMethodPrototype(ObjcImpDecl); // parse optional ';' if (Tok.getKind() == tok::semi) ConsumeToken(); diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index 0a7ea58b04..9743da73f1 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -22,6 +22,7 @@ Parser::Parser(Preprocessor &pp, Action &actions) CurScope = 0; NumCachedScopes = 0; ParenCount = BracketCount = BraceCount = 0; + ObjcImpDecl = 0; } /// Out-of-line virtual destructor to provide home for Action class. diff --git a/Sema/Sema.h b/Sema/Sema.h index b7500f8688..cabaae92c0 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -347,6 +347,17 @@ public: TypeTy *Ty, SourceLocation RParenLoc); + // Objective-C declarations. + virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + IdentifierInfo **ProtocolNames, unsigned NumProtocols, + AttributeList *AttrList); + + virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts); + private: // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts // functions and arrays to their respective pointers (C99 6.3.2.1). diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index f2a8f4d8ec..50cde4e410 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -26,7 +26,11 @@ using namespace clang; Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { - return dyn_cast_or_null(II.getFETokenInfo()); + Decl *IIDecl = II.getFETokenInfo(); + if (dyn_cast_or_null(IIDecl) || + dyn_cast_or_null(IIDecl)) + return IIDecl; + return 0; } void Sema::PopScope(SourceLocation Loc, Scope *S) { @@ -835,6 +839,45 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, return NewTD; } +Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + IdentifierInfo **ProtocolNames, unsigned NumProtocols, + AttributeList *AttrList) { + assert(ClassName && "Missing class identifier"); + ObjcInterfaceDecl *IDecl; + + IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, ClassName); + + // Chain & install the interface decl into the identifier. + IDecl->setNext(ClassName->getFETokenInfo()); + ClassName->setFETokenInfo(IDecl); + return IDecl; +} + +/// ObjcClassDeclaration - +/// Scope will always be top level file scope. +Action::DeclTy * +Sema::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, unsigned NumElts) { + ObjcClassDecl *CDecl = new ObjcClassDecl(AtClassLoc, NumElts); + + for (unsigned i = 0; i != NumElts; ++i) { + ObjcInterfaceDecl *IDecl; + + IDecl = new ObjcInterfaceDecl(SourceLocation(), IdentList[i], true); + // Chain & install the interface decl into the identifier. + IDecl->setNext(IdentList[i]->getFETokenInfo()); + IdentList[i]->setFETokenInfo(IDecl); + + // Remember that this needs to be removed when the scope is popped. + S->AddDecl(IdentList[i]); + + CDecl->setInterfaceDecl((int)i, IDecl); + } + return CDecl; +} + /// ParseTag - This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. diff --git a/Sema/SemaType.cpp b/Sema/SemaType.cpp index 17b34628b5..75f07d8d54 100644 --- a/Sema/SemaType.cpp +++ b/Sema/SemaType.cpp @@ -102,6 +102,10 @@ static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) { assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "Can't handle qualifiers on typedef names yet!"); + // FIXME: Adding a TST_objcInterface clause doesn't seem ideal, so + // we have this "hack" for now... + if (isa(D)) + return Ctx.getObjcInterfaceType(cast(D)); // TypeQuals handled by caller. return Ctx.getTypedefType(cast(D)); } diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 4502babadb..1d39bb3b70 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -109,6 +109,7 @@ public: /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. QualType getTypedefType(TypedefDecl *Decl); + QualType getObjcInterfaceType(ObjcInterfaceDecl *Decl); /// getTypeOfType - GCC extension. QualType getTypeOfExpr(Expr *e); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index f75b475689..2bb8243658 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -34,7 +34,7 @@ public: // Concrete sub-classes of ValueDecl Function, BlockVariable, FileVariable, ParmVariable, EnumConstant, // Concrete sub-classes of TypeDecl - Typedef, Struct, Union, Class, Enum, + Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, // Concrete sub-class of Decl Field }; @@ -503,6 +503,47 @@ public: static bool classof(const RecordDecl *D) { return true; } }; +class ObjcInterfaceDecl : public TypeDecl { + /// Ivars/NumIvars - This is a new[]'d array of pointers to Decls. + FieldDecl **Ivars; // Null if not defined. + int NumIvars; // -1 if not defined. + + bool isForwardDecl; // declared with @class. +public: + ObjcInterfaceDecl(SourceLocation L, IdentifierInfo *Id, bool FD = false) + : TypeDecl(ObjcInterface, L, Id, 0), Ivars(0), NumIvars(-1), + isForwardDecl(FD) { } + + void addInstanceVariable(FieldDecl ivar); + + static bool classof(const Decl *D) { + return D->getKind() == ObjcInterface; + } + static bool classof(const ObjcInterfaceDecl *D) { return true; } +}; + +class ObjcClassDecl : public TypeDecl { + ObjcInterfaceDecl **ForwardDecls; // Null if not defined. + int NumForwardDecls; // -1 if not defined. +public: + ObjcClassDecl(SourceLocation L, unsigned nElts) + : TypeDecl(ObjcClass, L, 0, 0) { + if (nElts) { + ForwardDecls = new ObjcInterfaceDecl*[nElts]; + bzero(ForwardDecls, nElts*sizeof(ObjcInterfaceDecl*)); + } + NumForwardDecls = nElts; + } + void setInterfaceDecl(int idx, ObjcInterfaceDecl *OID) { + assert((idx < NumForwardDecls) && "index out of range"); + ForwardDecls[idx] = OID; + } + static bool classof(const Decl *D) { + return D->getKind() == ObjcClass; + } + static bool classof(const ObjcClassDecl *D) { return true; } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 170580688b..26226de912 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -31,6 +31,7 @@ namespace clang { class TagDecl; class RecordDecl; class EnumDecl; + class ObjcInterfaceDecl; class Expr; class SourceLocation; class PointerType; @@ -203,6 +204,7 @@ public: Vector, OCUVector, FunctionNoProto, FunctionProto, TypeName, Tagged, + ObjcInterface, TypeOfExp, TypeOfTyp // GNU typeof extension. }; private: @@ -810,6 +812,23 @@ public: static bool classof(const TagType *) { return true; } }; +class ObjcInterfaceType : public Type { + ObjcInterfaceDecl *Decl; + ObjcInterfaceType(ObjcInterfaceDecl *D) : + Type(ObjcInterface, QualType()), Decl(D) { } + friend class ASTContext; // ASTContext creates these. +public: + + ObjcInterfaceDecl *getDecl() const { return Decl; } + + virtual void getAsStringInternal(std::string &InnerString) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == ObjcInterface; + } + static bool classof(const ObjcInterfaceType *) { return true; } +}; + /// RecordType - This is a helper class that allows the use of isa/cast/dyncast /// to detect TagType objects of structs/unions/classes. class RecordType : public TagType { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 20845ad9d6..5d0262fdb3 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -136,9 +136,9 @@ public: return 0; } - virtual DeclTy *ParsedObjcClassDeclaration(Scope *S, - IdentifierInfo **IdentList, - unsigned NumElts) { + virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts) { return 0; } @@ -440,25 +440,30 @@ public: AttributeList *AttrList) { return 0; } - virtual void ObjCContinueClassInterface(SourceLocation InterfaceLoc) { + virtual void ObjcAddInstanceVariable(DeclTy *ClassDec, DeclTy *Ivars, + tok::ObjCKeywordKind visibility) { return; } - virtual void ObjCStartCategoryInterface() { - return; - } - virtual void ObjCFinishInterface() { + virtual void ObjcAddMethod(DeclTy *ClassDec, DeclTy *Meth, + AttributeList *AttrList) { return; } virtual DeclTy *ObjcBuildMethodDeclaration( SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, - ObjcKeywordInfo *Keywords, unsigned NumKeywords, AttributeList *attrs) { + ObjcKeywordInfo *Keywords, unsigned NumKeywords) { return 0; } virtual DeclTy *ObjcBuildMethodDeclaration( SourceLocation MethodLoc, tok::TokenKind MethodType, TypeTy *ReturnType, - IdentifierInfo *SelectorName, AttributeList *attrs) { + IdentifierInfo *SelectorName) { return 0; } + virtual void ObjCStartCategoryInterface() { // FIXME + return; + } + virtual void ObjCFinishInterface() { + return; + } //===----------------------- Obj-C Expressions --------------------------===// virtual ExprResult ParseObjCStringLiteral(ExprTy *string) { @@ -496,10 +501,15 @@ public: /// they are removed from the IdentifierInfo::FETokenInfo field. virtual void PopScope(SourceLocation Loc, Scope *S); - virtual DeclTy *ParsedObjcClassDeclaration(Scope *S, - IdentifierInfo **IdentList, - unsigned NumElts); + virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts); + virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + IdentifierInfo **ProtocolNames, unsigned NumProtocols, + AttributeList *AttrList); }; } // end namespace clang diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index c49d242ab5..40e51bf75d 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -253,17 +253,17 @@ private: void ParseSimpleAsm(); void ParseAsmStringLiteral(); - // Objective-C External Declarations + // Objective-C External Declarations DeclTy *ParseObjCAtDirectives(); DeclTy *ParseObjCAtClassDeclaration(SourceLocation atLoc); DeclTy *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, AttributeList *prefixAttrs = 0); - void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, - llvm::SmallVectorImpl &IvarDecls); + void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl); bool ParseObjCProtocolReferences(llvm::SmallVectorImpl &); - void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, - llvm::SmallVectorImpl &MethodDecls); + void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl); DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc); + + DeclTy *ObjcImpDecl; DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc); DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc); DeclTy *ParseObjCAtAliasDeclaration(SourceLocation atLoc); @@ -288,7 +288,7 @@ private: TypeTy *ParseObjCTypeName(); void ParseObjCMethodRequirement(); - DeclTy *ParseObjCMethodPrototype(bool decl); + DeclTy *ParseObjCMethodPrototype(DeclTy *classOrCat); DeclTy *ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc); void ParseObjCPropertyAttribute(DeclTy *interfaceDecl); void ParseObjCPropertyDecl(DeclTy *interfaceDecl); diff --git a/test/Sema/cocoa.m b/test/Sema/cocoa.m index 955db7a1cf..4c98b07aca 100644 --- a/test/Sema/cocoa.m +++ b/test/Sema/cocoa.m @@ -1,4 +1,4 @@ -// RUN: clang %s -parse-noop -arch ppc +// RUN: clang %s -arch ppc #ifdef __APPLE__ #include #endif