diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp index febb19e27230f631a01a09d6cbe0c2f85fcb0f72..5f0b6b2d27df826c8d5e9fb8f9646b34de32e6fb 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp +++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp @@ -51,6 +51,7 @@ void CheckUndefinedSymbols::setGlobalNamespaceBinding(NamespaceBindingPtr global { _globalNamespaceBinding = globalNamespaceBinding; _types.clear(); + _protocols.clear(); if (_globalNamespaceBinding) { QSet<NamespaceBinding *> processed; @@ -130,6 +131,20 @@ void CheckUndefinedSymbols::addType(Name *name) _types.insert(QByteArray(id->chars(), id->size())); } +void CheckUndefinedSymbols::addProtocol(Name *name) +{ + if (!name) + return; + + if (Identifier *id = name->identifier()) + _protocols.insert(QByteArray(id->chars(), id->size())); +} + +bool CheckUndefinedSymbols::isProtocol(const QByteArray &name) const +{ + return _protocols.contains(name); +} + void CheckUndefinedSymbols::buildTypeMap(Class *klass) { addType(klass->name()); @@ -186,9 +201,9 @@ void CheckUndefinedSymbols::buildTypeMap(NamespaceBinding *binding, QSet<Namespa for (unsigned i = 0; i < klass->memberCount(); ++i) buildMemberTypeMap(klass->memberAt(i)); } else if (ObjCForwardProtocolDeclaration *fProto = member->asObjCForwardProtocolDeclaration()) { - addType(fProto->name()); + addProtocol(fProto->name()); } else if (ObjCProtocol *proto = member->asObjCProtocol()) { - addType(proto->name()); + addProtocol(proto->name()); for (unsigned i = 0; i < proto->memberCount(); ++i) buildMemberTypeMap(proto->memberAt(i)); @@ -466,3 +481,53 @@ bool CheckUndefinedSymbols::visit(SizeofExpressionAST *ast) return true; } + +bool CheckUndefinedSymbols::visit(ObjCClassDeclarationAST *ast) +{ + if (NameAST *nameAST = ast->superclass) { + bool resolvedSuperClassName = false; + + if (Name *name = nameAST->name) { + Identifier *id = name->identifier(); + const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size()); + if (isType(spell)) + resolvedSuperClassName = true; + } + + if (! resolvedSuperClassName) { + translationUnit()->warning(nameAST->firstToken(), + "expected class-name after ':' token"); + } + } + + return true; +} + +bool CheckUndefinedSymbols::visit(ObjCProtocolRefsAST *ast) +{ + for (IdentifierListAST *iter = ast->identifier_list; iter; iter = iter->next) { + if (NameAST *nameAST = iter->name) { + bool resolvedProtocolName = false; + + if (Name *name = nameAST->name) { + Identifier *id = name->identifier(); + const QByteArray spell = QByteArray::fromRawData(id->chars(), id->size()); + if (isProtocol(spell)) + resolvedProtocolName = true; + } + + if (!resolvedProtocolName) { + char after; + + if (iter == ast->identifier_list) + after = '<'; + else + after = ','; + + translationUnit()->warning(nameAST->firstToken(), "expected protocol name after '%c' token", after); + } + } + } + + return false; +} diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h index 745ee50b11124942e2398f8913a6121e8f333ebf..fbdca0f94ec9d2c1fdc7629d8fc0516b693bde3b 100644 --- a/src/libs/cplusplus/CheckUndefinedSymbols.h +++ b/src/libs/cplusplus/CheckUndefinedSymbols.h @@ -59,6 +59,8 @@ protected: void buildTypeMap(Class *klass); void buildMemberTypeMap(Symbol *member); void buildTypeMap(NamespaceBinding *binding, QSet<NamespaceBinding *> *processed); + void addProtocol(Name *name); + bool isProtocol(const QByteArray &name) const; FunctionDeclaratorAST *currentFunctionDeclarator() const; CompoundStatementAST *compoundStatement() const; @@ -92,6 +94,9 @@ protected: virtual bool visit(CastExpressionAST *ast); virtual bool visit(SizeofExpressionAST *ast); + virtual bool visit(ObjCClassDeclarationAST *ast); + virtual bool visit(ObjCProtocolRefsAST *ast); + private: Document::Ptr _doc; NamespaceBindingPtr _globalNamespaceBinding; @@ -100,6 +105,7 @@ private: QList<TemplateDeclarationAST *> _templateDeclarationStack; QList<CompoundStatementAST *> _compoundStatementStack; QSet<QByteArray> _types; + QSet<QByteArray> _protocols; QSet<QByteArray> _namespaceNames; }; diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 148cad3b956b67c90d6e0d4af07bb9c4fabfc6e8..21e8a1504c014fe5e27de1fc12d9eacc895c77ec 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -2359,6 +2359,8 @@ unsigned ObjCMethodPrototypeAST::lastToken() const { if (attributes) return attributes->lastToken(); + else if (dot_dot_dot_token) + return dot_dot_dot_token + 1; else if (arguments) return arguments->lastToken(); else if (type_name) diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index b118a1dd169d7d88a5efbc425fd10f753292e945..4af1971e2ee357522755d2dfcb0e087ad155c068 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -2994,6 +2994,7 @@ public: ObjCTypeNameAST *type_name; ObjCSelectorAST *selector; ObjCMessageArgumentDeclarationListAST *arguments; + unsigned dot_dot_dot_token; SpecifierAST *attributes; public: // annotations diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index eaa49eb173e06170b4ba3efc1551e35e688f0174..2467d4c56b0479d63e2a0699e71ff478a98a32ae 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -137,6 +137,8 @@ class ForwardClassDeclaration; class Token; // Objective-C symbols +class ObjCBaseClass; +class ObjCBaseProtocol; class ObjCClass; class ObjCForwardClassDeclaration; class ObjCProtocol; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 69e645b1be981c3f5815fe8b5e5a49ca0d44253f..4b2604de407ef54f7b671f5007c8b00cf1ca6530 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -57,6 +57,7 @@ #include "Control.h" #include "Literals.h" #include <cassert> +#include <QtCore/QByteArray> CPLUSPLUS_BEGIN_NAMESPACE @@ -506,11 +507,25 @@ bool CheckDeclaration::visit(ObjCProtocolDeclarationAST *ast) ObjCProtocol *protocol = control()->newObjCProtocol(sourceLocation, protocolName); protocol->setStartOffset(tokenAt(ast->firstToken()).offset); protocol->setEndOffset(tokenAt(ast->lastToken()).offset); - ast->symbol = protocol; + if (ast->protocol_refs && ast->protocol_refs->identifier_list) { + for (IdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) { + NameAST* name = iter->name; + Name *protocolName = semantic()->check(name, _scope); + ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName); + protocol->addProtocol(baseProtocol); + } + } + + int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Public); + for (DeclarationListAST *it = ast->member_declarations; it; it = it->next) { + semantic()->check(it->declaration, protocol->members()); + } + (void) semantic()->switchObjCVisibility(previousObjCVisibility); + + ast->symbol = protocol; _scope->enterSymbol(protocol); - // TODO EV: walk protocols and method prototypes return false; } @@ -562,7 +577,21 @@ bool CheckDeclaration::visit(ObjCClassDeclarationAST *ast) klass->setCategoryName(categoryName); } - // TODO: super-class, and protocols (EV) + if (ast->superclass) { + Name *superClassName = semantic()->check(ast->superclass, _scope); + ObjCBaseClass *superKlass = control()->newObjCBaseClass(ast->superclass->firstToken(), superClassName); + klass->setBaseClass(superKlass); + } + + if (ast->protocol_refs && ast->protocol_refs->identifier_list) { + for (IdentifierListAST *iter = ast->protocol_refs->identifier_list; iter; iter = iter->next) { + NameAST* name = iter->name; + Name *protocolName = semantic()->check(name, _scope); + ObjCBaseProtocol *baseProtocol = control()->newObjCBaseProtocol(name->firstToken(), protocolName); + klass->addProtocol(baseProtocol); + } + } + _scope->enterSymbol(klass); int previousObjCVisibility = semantic()->switchObjCVisibility(Function::Protected); @@ -627,4 +656,86 @@ bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast) return false; } +enum PropertyAttributes { + None = 0, + Assign = 1 << 0, + Retain = 1 << 1, + Copy = 1 << 2, + ReadOnly = 1 << 3, + ReadWrite = 1 << 4, + Getter = 1 << 5, + Setter = 1 << 6, + NonAtomic = 1 << 7, + + WritabilityMask = ReadOnly | ReadWrite, + SetterSemanticsMask = Assign | Retain | Copy, +}; + +bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst, + int &flags, + int attr) +{ + if (flags & attr) { + translationUnit()->warning(attrAst->attribute_identifier_token, + "duplicate property attribute \"%s\"", + spell(attrAst->attribute_identifier_token)); + return false; + } else { + flags |= attr; + return true; + } +} + +bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast) +{ + int propAttrs = None; + + for (ObjCPropertyAttributeListAST *iter= ast->property_attributes; iter; iter = iter->next) { + ObjCPropertyAttributeAST *attrAst = iter->attr; + if (!attrAst) + continue; + + const char *attrName = spell(attrAst->attribute_identifier_token); + if (!qstrcmp("getter", attrName)) { + if (checkPropertyAttribute(attrAst, propAttrs, Getter)) { + // TODO: find method declaration for getter + } + } else if (!qstrcmp("setter", attrName)) { + if (checkPropertyAttribute(attrAst, propAttrs, Setter)) { + // TODO: find method declaration for setter + } + } else if (!qstrcmp("readwrite", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, ReadWrite); + } else if (!qstrcmp("readonly", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, ReadOnly); + } else if (!qstrcmp("assign", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, Assign); + } else if (!qstrcmp("retain", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, Retain); + } else if (!qstrcmp("copy", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, Copy); + } else if (!qstrcmp("nonatomic", attrName)) { + checkPropertyAttribute(attrAst, propAttrs, NonAtomic); + } + } + + if (propAttrs & ReadOnly && propAttrs & ReadWrite) + // Should this be an error instead of only a warning? + translationUnit()->warning(ast->property_token, + "property can have at most one attribute \"readonly\" or \"readwrite\" specified"); + int setterSemAttrs = propAttrs & SetterSemanticsMask; + if (setterSemAttrs + && setterSemAttrs != Assign + && setterSemAttrs != Retain + && setterSemAttrs != Copy) { + // Should this be an error instead of only a warning? + translationUnit()->warning(ast->property_token, + "property can have at most one attribute \"assign\", \"retain\", or \"copy\" specified"); + } + + // TODO: Check if the next line is correct (EV) + semantic()->check(ast->simple_declaration, _scope); + return false; +} + CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index 27869c75ca3147cf34c8643686cd6aee66218afb..93ef59f941fbb4a313c13a8c2f4686cbce8f61c6 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -97,7 +97,12 @@ protected: virtual bool visit(ObjCClassForwardDeclarationAST *ast); virtual bool visit(ObjCMethodDeclarationAST *ast); virtual bool visit(ObjCVisibilityDeclarationAST *ast); + virtual bool visit(ObjCPropertyDeclarationAST *ast); +private: + bool checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst, + int &flags, + int attr); private: DeclarationAST *_declaration; Scope *_scope; diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp index 5186055bca9b0f160539df659269d0ebd62ed247..5867d6180aa8a254af1f2952c0a13828cf62da12 100644 --- a/src/shared/cplusplus/CheckDeclarator.cpp +++ b/src/shared/cplusplus/CheckDeclarator.cpp @@ -265,14 +265,15 @@ bool CheckDeclarator::visit(ObjCMethodPrototypeAST *ast) method->setReturnType(returnType); if (ast->selector && ast->selector->asObjCSelectorWithArguments()) { - // TODO: check the parameters (EV) - // fun->setVariadic(...); // TODO: add arguments (EV) for (ObjCMessageArgumentDeclarationListAST *it = ast->arguments; it; it = it->next) { ObjCMessageArgumentDeclarationAST *argDecl = it->argument_declaration; semantic()->check(argDecl, method->arguments()); } + + if (ast->dot_dot_dot_token) + method->setVariadic(true); } _fullySpecifiedType = FullySpecifiedType(method); diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp index 9cbef353775cfebc9dc7d24b106d4928bf08626f..d4de2c55176d6fb570c949e2e31f036d52e5d13a 100644 --- a/src/shared/cplusplus/CheckSpecifier.cpp +++ b/src/shared/cplusplus/CheckSpecifier.cpp @@ -416,8 +416,8 @@ bool CheckSpecifier::visit(AttributeSpecifierAST *ast) bool CheckSpecifier::visit(ObjCTypeNameAST * /*ast*/) { // TODO: implement this (EV) - _fullySpecifiedType = FullySpecifiedType(); - return false; +// _fullySpecifiedType = FullySpecifiedType(); + return true; } CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp index 07e46fd1ae234e1ddf798050cd82cffcff64fc1f..6338d99fd2251d595379ac2a2f4a3e0ae7b31340 100644 --- a/src/shared/cplusplus/Control.cpp +++ b/src/shared/cplusplus/Control.cpp @@ -128,6 +128,8 @@ public: delete_array_entries(enums); delete_array_entries(usingDeclarations); delete_array_entries(classForwardDeclarations); + delete_array_entries(objcBaseClasses); + delete_array_entries(objcBaseProtocols); delete_array_entries(objcClasses); delete_array_entries(objcProtocols); delete_array_entries(objcForwardClassDeclarations); @@ -348,6 +350,20 @@ public: return c; } + ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, Name *name) + { + ObjCBaseClass *c = new ObjCBaseClass(translationUnit, sourceLocation, name); + objcBaseClasses.push_back(c); + return c; + } + + ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, Name *name) + { + ObjCBaseProtocol *p = new ObjCBaseProtocol(translationUnit, sourceLocation, name); + objcBaseProtocols.push_back(p); + return p; + } + ObjCClass *newObjCClass(unsigned sourceLocation, Name *name) { ObjCClass *c = new ObjCClass(translationUnit, sourceLocation, name); @@ -561,6 +577,8 @@ public: std::vector<Enum *> enums; std::vector<UsingDeclaration *> usingDeclarations; std::vector<ForwardClassDeclaration *> classForwardDeclarations; + std::vector<ObjCBaseClass *> objcBaseClasses; + std::vector<ObjCBaseProtocol *> objcBaseProtocols; std::vector<ObjCClass *> objcClasses; std::vector<ObjCProtocol *> objcProtocols; std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations; @@ -740,6 +758,12 @@ ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLoca Name *name) { return d->newForwardClassDeclaration(sourceLocation, name); } +ObjCBaseClass *Control::newObjCBaseClass(unsigned sourceLocation, Name *name) +{ return d->newObjCBaseClass(sourceLocation, name); } + +ObjCBaseProtocol *Control::newObjCBaseProtocol(unsigned sourceLocation, Name *name) +{ return d->newObjCBaseProtocol(sourceLocation, name); } + ObjCClass *Control::newObjCClass(unsigned sourceLocation, Name *name) { return d->newObjCClass(sourceLocation, name); } diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h index 323740b742288d17112679bf91e9874c4f41e4a8..060be182b685c12e924b25bbd1562c40a479aa7b 100644 --- a/src/shared/cplusplus/Control.h +++ b/src/shared/cplusplus/Control.h @@ -166,6 +166,9 @@ public: /// Creates a new ForwardClassDeclaration symbol. ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0); + ObjCBaseClass *newObjCBaseClass(unsigned sourceLocation, Name *name); + ObjCBaseProtocol *newObjCBaseProtocol(unsigned sourceLocation, Name *name); + /// Creates a new Objective-C class symbol. ObjCClass *newObjCClass(unsigned sourceLocation, Name *name = 0); diff --git a/src/shared/cplusplus/ObjectiveCTypeQualifiers.cpp b/src/shared/cplusplus/ObjectiveCTypeQualifiers.cpp index fa2b7d331420422fdbc6e4fec876f04e60b44377..d12d7c322c169a938fad92c9206ac3a16ba2ffc4 100644 --- a/src/shared/cplusplus/ObjectiveCTypeQualifiers.cpp +++ b/src/shared/cplusplus/ObjectiveCTypeQualifiers.cpp @@ -51,6 +51,19 @@ static inline int classify3(const char *s) { return Token_identifier; } +static inline int classify4(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'p') { + if (s[3] == 'y') { + return Token_copy; + } + } + } + } + return Token_identifier; +} + static inline int classify5(const char *s) { if (s[0] == 'b') { if (s[1] == 'y') { @@ -78,7 +91,20 @@ static inline int classify5(const char *s) { } static inline int classify6(const char *s) { - if (s[0] == 'b') { + if (s[0] == 'a') { + if (s[1] == 's') { + if (s[2] == 's') { + if (s[3] == 'i') { + if (s[4] == 'g') { + if (s[5] == 'n') { + return Token_assign; + } + } + } + } + } + } + else if (s[0] == 'b') { if (s[1] == 'y') { if (s[2] == 'c') { if (s[3] == 'o') { @@ -91,6 +117,32 @@ static inline int classify6(const char *s) { } } } + else if (s[0] == 'g') { + if (s[1] == 'e') { + if (s[2] == 't') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'r') { + return Token_getter; + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'e') { + if (s[2] == 't') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'r') { + return Token_setter; + } + } + } + } + } + } else if (s[0] == 'o') { if (s[1] == 'n') { if (s[2] == 'e') { @@ -104,15 +156,93 @@ static inline int classify6(const char *s) { } } } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 't') { + if (s[3] == 'a') { + if (s[4] == 'i') { + if (s[5] == 'n') { + return Token_retain; + } + } + } + } + } + } return Token_identifier; } +static inline int classify8(const char *s) { + if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'a') { + if (s[3] == 'd') { + if (s[4] == 'o') { + if (s[5] == 'n') { + if (s[6] == 'l') { + if (s[7] == 'y') { + return Token_readonly; + } + } + } + } + } + } + } + } + return Token_identifier; +} + +static inline int classify9(const char *s) { + if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 't') { + if (s[5] == 'o') { + if (s[6] == 'm') { + if (s[7] == 'i') { + if (s[8] == 'c') { + return Token_nonatomic; + } + } + } + } + } + } + } + } + } else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'a') { + if (s[3] == 'd') { + if (s[4] == 'w') { + if (s[5] == 'r') { + if (s[6] == 'i') { + if (s[7] == 't') { + if (s[8] == 'e') { + return Token_readwrite; + } + } + } + } + } + } + } + } + } + return Token_identifier; +} + int classifyObjectiveCTypeQualifiers(const char *s, int n) { switch (n) { case 2: return classify2(s); case 3: return classify3(s); + case 4: return classify4(s); case 5: return classify5(s); case 6: return classify6(s); + case 8: return classify8(s); + case 9: return classify9(s); default: return Token_identifier; } // switch } diff --git a/src/shared/cplusplus/ObjectiveCTypeQualifiers.h b/src/shared/cplusplus/ObjectiveCTypeQualifiers.h index 35a69e9299d407019b771b7990001b36ecf00805..0f9cdfd6774ab75fe4e8ef8665e06f97271cfff6 100644 --- a/src/shared/cplusplus/ObjectiveCTypeQualifiers.h +++ b/src/shared/cplusplus/ObjectiveCTypeQualifiers.h @@ -37,10 +37,18 @@ CPLUSPLUS_BEGIN_NAMESPACE enum { Token_in, Token_out, + Token_copy, Token_byref, Token_inout, + Token_assign, Token_bycopy, + Token_getter, + Token_retain, + Token_setter, Token_oneway, + Token_readonly, + Token_nonatomic, + Token_readwrite, Token_identifier }; diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 45905829fc11948fcf8154864f9058f433f6be96..d335b5ebfff5cbc73eb6174857d6a6cce78ec245 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -4544,7 +4544,13 @@ bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierAST *a last->comma_token = consumeToken(); last->next = new (_pool) ObjCPropertyAttributeListAST; last = last->next; - parseObjCPropertyAttribute(last->attr); + if (!parseObjCPropertyAttribute(last->attr)) { + _translationUnit->error(_tokenIndex, "expected token `%s' got `%s'", + Token::name(T_IDENTIFIER), tok().spell()); + while (LA() != T_RPAREN) + consumeToken(); + break; + } } } @@ -4597,15 +4603,15 @@ bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node) lastArg->argument_declaration = declaration; } - // TODO EV: get this in the ast while (LA() == T_COMMA) { consumeToken(); if (LA() == T_DOT_DOT_DOT) { - consumeToken(); + ast->dot_dot_dot_token = consumeToken(); break; } + // TODO: Is this still valid, and if so, should it be stored in the AST? (EV) DeclarationAST *parameter_declaration = 0; parseParameterDeclaration(parameter_declaration); } @@ -4639,28 +4645,43 @@ bool Parser::parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node) return false; node = new (_pool) ObjCPropertyAttributeAST; - match(T_IDENTIFIER, &(node->attribute_identifier_token)); - if (LA() == T_EQUAL) { - node->equals_token = consumeToken(); - unsigned identifier_token = 0; - match(T_IDENTIFIER, &identifier_token); + Identifier *id = tok().identifier; + const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size()); + switch (k) { + case Token_copy: + case Token_assign: + case Token_retain: + case Token_readonly: + case Token_readwrite: + case Token_nonatomic: + node->attribute_identifier_token = consumeToken(); + return true; - if (LA() == T_COLON) { - ObjCSelectorWithArgumentsAST *selector = new (_pool) ObjCSelectorWithArgumentsAST; - selector->selector_arguments = new (_pool) ObjCSelectorArgumentListAST; - selector->selector_arguments->argument = new (_pool) ObjCSelectorArgumentAST; - selector->selector_arguments->argument->name_token = identifier_token; - selector->selector_arguments->argument->colon_token = consumeToken(); - node->method_selector = selector; - } else { - ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST; - selector->name_token = identifier_token; - node->method_selector = selector; - } + case Token_getter: { + node->attribute_identifier_token = consumeToken(); + match(T_EQUAL, &(node->equals_token)); + ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST; + match(T_IDENTIFIER, &(selector->name_token)); + node->method_selector = selector; + return true; } - return true; + case Token_setter: { + node->attribute_identifier_token = consumeToken(); + match(T_EQUAL, &(node->equals_token)); + ObjCSelectorWithArgumentsAST *selector = new (_pool) ObjCSelectorWithArgumentsAST; + selector->selector_arguments = new (_pool) ObjCSelectorArgumentListAST; + selector->selector_arguments->argument = new (_pool) ObjCSelectorArgumentAST; + match(T_IDENTIFIER, &(selector->selector_arguments->argument->name_token)); + match(T_COLON, &(selector->selector_arguments->argument->colon_token)); + node->method_selector = selector; + return true; + } + + default: + return false; + } } // objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h index d0de211a52399e8b67b2cffff2f82fc5481c7108..511e14c9f21def5bc3aa94af5869c6b19a70440b 100644 --- a/src/shared/cplusplus/Symbol.h +++ b/src/shared/cplusplus/Symbol.h @@ -210,6 +210,9 @@ public: /// Returns true if this Symbol is a ForwardClassDeclaration. bool isForwardClassDeclaration() const; + bool isObjCBaseClass() const; + bool isObjCBaseProtocol() const; + /// Returns true if this Symbol is an Objective-C Class declaration. bool isObjCClass() const; @@ -237,6 +240,8 @@ public: virtual const Argument *asArgument() const { return 0; } virtual const BaseClass *asBaseClass() const { return 0; } virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; } + virtual const ObjCBaseClass *asObjCBaseClass() const { return 0; } + virtual const ObjCBaseProtocol *asObjCBaseProtocol() const { return 0; } virtual const ObjCClass *asObjCClass() const { return 0; } virtual const ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() const { return 0; } virtual const ObjCProtocol *asObjCProtocol() const { return 0; } @@ -255,6 +260,8 @@ public: virtual Argument *asArgument() { return 0; } virtual BaseClass *asBaseClass() { return 0; } virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; } + virtual ObjCBaseClass *asObjCBaseClass() { return 0; } + virtual ObjCBaseProtocol *asObjCBaseProtocol() { return 0; } virtual ObjCClass *asObjCClass() { return 0; } virtual ObjCForwardClassDeclaration *asObjCForwardClassDeclaration() { return 0; } virtual ObjCProtocol *asObjCProtocol() { return 0; } diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h index 939dad9068681723c531c84039ca6a1b75a5d58f..8708ab03212ea7c5a08f80a09441078e875e564c 100644 --- a/src/shared/cplusplus/SymbolVisitor.h +++ b/src/shared/cplusplus/SymbolVisitor.h @@ -81,6 +81,8 @@ public: virtual bool visit(ForwardClassDeclaration *) { return true; } // Objective-C + virtual bool visit(ObjCBaseClass *) { return true; } + virtual bool visit(ObjCBaseProtocol *) { return true; } virtual bool visit(ObjCClass *) { return true; } virtual bool visit(ObjCForwardClassDeclaration *) { return true; } virtual bool visit(ObjCProtocol *) { return true; } diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index c5259c9fe8396482400bcbea87a1e4fb0b44a631..d5fa07a99b9b103d09d7a5944b34a743de196ea2 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -561,6 +561,32 @@ void Class::visitSymbol0(SymbolVisitor *visitor) } } +ObjCBaseClass::ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name) +{ } + +ObjCBaseClass::~ObjCBaseClass() +{ } + +FullySpecifiedType ObjCBaseClass::type() const +{ return FullySpecifiedType(); } + +void ObjCBaseClass::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +ObjCBaseProtocol::ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name) +{ } + +ObjCBaseProtocol::~ObjCBaseProtocol() +{ } + +FullySpecifiedType ObjCBaseProtocol::type() const +{ return FullySpecifiedType(); } + +void ObjCBaseProtocol::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name): ScopedSymbol(translationUnit, sourceLocation, name), _categoryName(0), diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index 3ac7182c9a0e1f200e3294a343bd925fe126fbb1..10eb0366bffce04386977009c63551c182c9ec69 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -476,6 +476,48 @@ private: Array<BaseClass *> _baseClasses; }; +class CPLUSPLUS_EXPORT ObjCBaseClass: public Symbol +{ +public: + ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~ObjCBaseClass(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + virtual const ObjCBaseClass *asObjCBaseClass() const + { return this; } + + virtual ObjCBaseClass *asObjCBaseClass() + { return this; } + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + +private: +}; + +class CPLUSPLUS_EXPORT ObjCBaseProtocol: public Symbol +{ +public: + ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~ObjCBaseProtocol(); + + // Symbol's interface + virtual FullySpecifiedType type() const; + + virtual const ObjCBaseProtocol *asObjCBaseProtocol() const + { return this; } + + virtual ObjCBaseProtocol *asObjCBaseProtocol() + { return this; } + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + +private: +}; + class CPLUSPLUS_EXPORT ObjCForwardProtocolDeclaration: public Symbol, public Type { public: @@ -511,6 +553,15 @@ public: ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); virtual ~ObjCProtocol(); + unsigned protocolCount() const + { return _protocols.count(); } + + ObjCBaseProtocol *protocolAt(unsigned index) const + { return _protocols.at(index); } + + void addProtocol(ObjCBaseProtocol *protocol) + { _protocols.push_back(protocol); } + // Symbol's interface virtual FullySpecifiedType type() const; @@ -534,7 +585,7 @@ protected: virtual void accept0(TypeVisitor *visitor); private: - Array<ObjCProtocol *> _protocols; + Array<ObjCBaseProtocol *> _protocols; }; class CPLUSPLUS_EXPORT ObjCForwardClassDeclaration: public Symbol, public Type @@ -579,18 +630,18 @@ public: Name *categoryName() const { return _categoryName; } void setCategoryName(Name *categoryName) { _categoryName = categoryName; } - ObjCClass *baseClass() const + ObjCBaseClass *baseClass() const { return _baseClass; } - void setBaseClass(ObjCClass *baseClass) + void setBaseClass(ObjCBaseClass *baseClass) { _baseClass = baseClass; } unsigned protocolCount() const { return _protocols.count(); } - ObjCProtocol *protocolAt(unsigned index) const + ObjCBaseProtocol *protocolAt(unsigned index) const { return _protocols.at(index); } - void addProtocol(ObjCProtocol *protocol) + void addProtocol(ObjCBaseProtocol *protocol) { _protocols.push_back(protocol); } // Symbol's interface @@ -618,8 +669,8 @@ protected: private: bool _isInterface; Name *_categoryName; - ObjCClass * _baseClass; - Array<ObjCProtocol *> _protocols; + ObjCBaseClass * _baseClass; + Array<ObjCBaseProtocol *> _protocols; }; class CPLUSPLUS_EXPORT ObjCMethod: public ScopedSymbol, public Type