diff --git a/src/libs/cplusplus/NamePrettyPrinter.cpp b/src/libs/cplusplus/NamePrettyPrinter.cpp index 75aa582cded3d691f0556857eee74a9cc2e4393f..788c418c09ab0401f43eac2630570eeb5e4ce1ab 100644 --- a/src/libs/cplusplus/NamePrettyPrinter.cpp +++ b/src/libs/cplusplus/NamePrettyPrinter.cpp @@ -253,3 +253,20 @@ void NamePrettyPrinter::visit(QualifiedNameId *name) _name += operator()(name->nameAt(index)); } } + +void NamePrettyPrinter::visit(SelectorNameId *name) +{ + for (unsigned i = 0; i < name->nameCount(); ++i) { + Name *n = name->nameAt(i); + if (!n) + continue; + + Identifier *id = n->identifier(); + if (id) { + _name += QString::fromLatin1(id->chars(), id->size()); + + if (name->hasArguments() || name->nameCount() > 1) + _name += ':'; + } + } +} diff --git a/src/libs/cplusplus/NamePrettyPrinter.h b/src/libs/cplusplus/NamePrettyPrinter.h index 2e0ef2c9b1c2129a20c1f296908664e13145d610..6704099009c61356f2c3dd1072a74a2448c376cd 100644 --- a/src/libs/cplusplus/NamePrettyPrinter.h +++ b/src/libs/cplusplus/NamePrettyPrinter.h @@ -55,6 +55,7 @@ protected: virtual void visit(OperatorNameId *name); virtual void visit(ConversionNameId *name); virtual void visit(QualifiedNameId *name); + virtual void visit(SelectorNameId *name); private: const Overview *_overview; diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp index 008fb97abe9d1bbd70e3ae29368f214092429c9a..ed119824af982dae33a84e66618d7845238ffc7c 100644 --- a/src/libs/cplusplus/OverviewModel.cpp +++ b/src/libs/cplusplus/OverviewModel.cpp @@ -164,6 +164,12 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const QString name = _overview.prettyName(symbol->name()); if (name.isEmpty()) name = QLatin1String("anonymous"); + if (symbol->isObjCForwardClassDeclaration()) + name = QLatin1String("@class ") + name; + if (symbol->isObjCForwardProtocolDeclaration() || symbol->isObjCProtocol()) + name = QLatin1String("@protocol ") + name; + if (symbol->isObjCClass()) + name = QLatin1String("@interface ") + name; if (! symbol->isScopedSymbol() || symbol->isFunction()) { QString type = _overview.prettyType(symbol->type()); if (! type.isEmpty()) { diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 0a16fa774ca54c413774a06f311ff0f19bbee162..cba0a7a39dc4a6ccd222125100c324e662b3554c 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -2080,6 +2080,9 @@ unsigned ObjCMessageExpressionAST::lastToken() const if (receiver_expression) return receiver_expression->lastToken(); + if (selector) + return selector->lastToken(); + if (argument_list) return argument_list->lastToken(); @@ -2107,7 +2110,7 @@ unsigned ObjCMessageArgumentListAST::lastToken() const unsigned ObjCMessageArgumentAST::firstToken() const { - return parameter_key_identifier; + return parameter_value_expression->firstToken(); } unsigned ObjCMessageArgumentAST::lastToken() const @@ -2115,10 +2118,8 @@ unsigned ObjCMessageArgumentAST::lastToken() const if (parameter_value_expression) return parameter_value_expression->lastToken(); - if (colon_token) - return colon_token + 1; - - return parameter_key_identifier + 1; + // ### assert? + return 0; } unsigned ObjCProtocolExpressionAST::firstToken() const diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index d9e541302870ef0e9ddbe162bda77ab6289f6c22..fb84d4d0a917634fcb5aa2403441a5ce768adf98 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -2644,8 +2644,6 @@ protected: class CPLUSPLUS_EXPORT ObjCMessageArgumentAST: public AST { public: - unsigned parameter_key_identifier; - unsigned colon_token; ExpressionAST *parameter_value_expression; public: @@ -2685,6 +2683,7 @@ class CPLUSPLUS_EXPORT ObjCMessageExpressionAST: public ExpressionAST public: unsigned lbracket_token; ExpressionAST *receiver_expression; + ObjCSelectorAST *selector; ObjCMessageArgumentListAST *argument_list; unsigned rbracket_token; diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 1fbb5a651b143b25ba962242f5dd3b1239d14a37..87e74d9ee485201666ac7f210e3e668a37d47615 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -1295,6 +1295,7 @@ ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) cons ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST; ast->lbracket_token = lbracket_token; if (receiver_expression) ast->receiver_expression = receiver_expression->clone(pool); + if (selector) ast->selector = selector->clone(pool); if (argument_list) ast->argument_list = argument_list->clone(pool); ast->rbracket_token = rbracket_token; return ast; @@ -1311,8 +1312,6 @@ ObjCMessageArgumentListAST *ObjCMessageArgumentListAST::clone(MemoryPool *pool) ObjCMessageArgumentAST *ObjCMessageArgumentAST::clone(MemoryPool *pool) const { ObjCMessageArgumentAST *ast = new (pool) ObjCMessageArgumentAST; - ast->parameter_key_identifier = parameter_key_identifier; - ast->colon_token = colon_token; if (parameter_value_expression) ast->parameter_value_expression = parameter_value_expression->clone(pool); return ast; } diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index f258ac1125e36ddca551f1aa75a95f9a12913398..a76d80df6bbd5e154adb2f2f5ddeab23997eedd1 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -1220,6 +1220,8 @@ void ObjCMessageExpressionAST::accept0(ASTVisitor *visitor) // visit ObjCMessageExpressionAST if (receiver_expression) accept(receiver_expression, visitor); + if (selector) + accept(selector, visitor); if (argument_list) accept(argument_list, visitor); // visit ExpressionAST @@ -1231,10 +1233,9 @@ void ObjCMessageArgumentListAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { // visit ObjCMessageArgumentListAST - if (arg) - accept(arg, visitor); - if (next) - accept(next, visitor); + for (ObjCMessageArgumentListAST *it = this; it; it = it->next) + if (it->arg) + accept(it->arg, visitor); // visit AST } visitor->endVisit(this); diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 76ee3061dc577f116fd6f86f236a89de3d9fa792..e85dda262f75e53246ab60ae45987cb12fea816c 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -100,6 +100,7 @@ class DestructorNameId; class OperatorNameId; class ConversionNameId; class QualifiedNameId; +class SelectorNameId; // types class FullySpecifiedType; @@ -138,6 +139,7 @@ class ObjCClass; class ObjCForwardClassDeclaration; class ObjCProtocol; class ObjCForwardProtocolDeclaration; +class ObjCMethod; CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 1a9877db156770919744b25d8899316818ee9d66..f3157e7bc673b5d3a802a337e2673b09119bf87e 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -598,6 +598,36 @@ bool CheckDeclaration::visit(ObjCMethodDeclarationAST *ast) return false; } +bool CheckDeclaration::visit(ObjCMethodDefinitionAST *ast) +{ + if (!ast->method_prototype) + return false; + + FullySpecifiedType ty = semantic()->check(ast->method_prototype, _scope); + Function *fun = ty.type()->asFunctionType(); + if (!fun) + return false; + + Declaration *symbol = control()->newDeclaration(ast->firstToken(), fun->name()); + symbol->setStartOffset(tokenAt(ast->firstToken()).offset); + symbol->setEndOffset(tokenAt(ast->lastToken()).offset); + + symbol->setType(fun->returnType()); + + symbol->setVisibility(semantic()->currentVisibility()); + + if (semantic()->isObjCClassMethod(ast->method_prototype->method_type_token)) + symbol->setStorage(Symbol::Static); + + _scope->enterSymbol(symbol); + + if (! semantic()->skipFunctionBodies()) { + semantic()->check(ast->function_body, fun->members()); + } + + return false; +} + bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast) { int accessSpecifier = tokenKind(ast->visibility_token); diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index 97c4d5ff449021aa30d173faf2e8b59b417cf540..b1880c5377f405ed2c9446f647c294655e113be2 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -96,6 +96,7 @@ protected: virtual bool visit(ObjCClassDeclarationAST *ast); virtual bool visit(ObjCClassInterfaceDefinitionAST *ast); virtual bool visit(ObjCMethodDeclarationAST *ast); + virtual bool visit(ObjCMethodDefinitionAST *ast); virtual bool visit(ObjCVisibilityDeclarationAST *ast); private: diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index 25cfe8ba43a70c5eeed90528879fda5614be4570..ac93a1a9de0c2603c11a9d48c35274728e8c7620 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -383,4 +383,29 @@ bool CheckExpression::visit(MemberAccessAST *ast) return false; } +bool CheckExpression::visit(ObjCMessageExpressionAST *ast) +{ + semantic()->check(ast->receiver_expression, _scope); + + if (Name *name = semantic()->check(ast->selector, _scope)) + _scope->addUse(ast->selector->firstToken(), name); + + accept(ast->argument_list); + return false; +} + +bool CheckExpression::visit(ObjCEncodeExpressionAST * /*ast*/) +{ + // TODO: visit the type name, but store the type here? (EV) + return true; +} + +bool CheckExpression::visit(ObjCSelectorExpressionAST *ast) +{ + if (Name *name = semantic()->check(ast->selector, _scope)) + _scope->addUse(ast->selector->firstToken(), name); + + return false; +} + CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h index dad53ed3b76abda3ff36c8b17ff1d28a5ea5108e..41c3393d7ae9e1279018dea938c525a63f9b0277 100644 --- a/src/shared/cplusplus/CheckExpression.h +++ b/src/shared/cplusplus/CheckExpression.h @@ -110,6 +110,11 @@ protected: virtual bool visit(PostIncrDecrAST *ast); virtual bool visit(MemberAccessAST *ast); + // ObjC + virtual bool visit(ObjCMessageExpressionAST *ast); + virtual bool visit(ObjCEncodeExpressionAST *ast); + virtual bool visit(ObjCSelectorExpressionAST *ast); + private: ExpressionAST *_expression; FullySpecifiedType _fullySpecifiedType; diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp index 48ab067f03b8ebdfd662eaa2a6126bc678531421..0fad66cccf97fc624d383a7c672a77f7aa94e882 100644 --- a/src/shared/cplusplus/CheckName.cpp +++ b/src/shared/cplusplus/CheckName.cpp @@ -376,8 +376,10 @@ bool CheckName::visit(TemplateIdAST *ast) bool CheckName::visit(ObjCSelectorWithoutArgumentsAST *ast) { + std::vector<Name *> names; Identifier *id = identifier(ast->name_token); - _name = control()->nameId(id); + names.push_back(control()->nameId(id)); + _name = control()->selectorNameId(&names[0], names.size(), false); ast->selector_name = _name; return false; @@ -392,7 +394,7 @@ bool CheckName::visit(ObjCSelectorWithArgumentsAST *ast) names.push_back(name); } - _name = control()->qualifiedNameId(&names[0], names.size(), false); + _name = control()->selectorNameId(&names[0], names.size(), true); ast->selector_name = _name; return false; diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp index 49f965f7da3caa9f38c986904a830d33f8323dcc..96a6719611969b41a52387b78905a5a083ae39b3 100644 --- a/src/shared/cplusplus/Control.cpp +++ b/src/shared/cplusplus/Control.cpp @@ -196,6 +196,15 @@ public: return it->second; } + SelectorNameId *findOrInsertSelectorNameId(const std::vector<Name *> &names, bool hasArguments) + { + const SelectorNameIdKey key(names, hasArguments); + std::map<SelectorNameIdKey, SelectorNameId *>::iterator it = selectorNameIds.lower_bound(key); + if (it == selectorNameIds.end() || it->first != key) + it = selectorNameIds.insert(it, std::make_pair(key, new SelectorNameId(&names[0], names.size(), hasArguments))); + return it->second; + } + IntegerType *findOrInsertIntegerType(int kind) { const int key = int(kind); @@ -423,6 +432,27 @@ public: } }; + struct SelectorNameIdKey { + std::vector<Name *> _names; + bool _hasArguments; + + SelectorNameIdKey(const std::vector<Name *> &names, bool hasArguments): _names(names), _hasArguments(hasArguments) {} + + bool operator==(const SelectorNameIdKey &other) const + { return _names == other._names && _hasArguments == other._hasArguments; } + + bool operator!=(const SelectorNameIdKey &other) const + { return !operator==(other); } + + bool operator<(const SelectorNameIdKey &other) const + { + if (_hasArguments == other._hasArguments) + return std::lexicographical_compare(_names.begin(), _names.end(), other._names.begin(), other._names.end()); + else + return _hasArguments < other._hasArguments; + } + }; + struct ArrayKey { FullySpecifiedType type; size_t size; @@ -491,6 +521,7 @@ public: std::map<FullySpecifiedType, ConversionNameId *> conversionNameIds; std::map<TemplateNameIdKey, TemplateNameId *> templateNameIds; std::map<QualifiedNameIdKey, QualifiedNameId *> qualifiedNameIds; + std::map<SelectorNameIdKey, SelectorNameId *> selectorNameIds; // types VoidType voidType; @@ -615,6 +646,15 @@ QualifiedNameId *Control::qualifiedNameId(Name *const *names, return d->findOrInsertQualifiedNameId(classOrNamespaceNames, isGlobal); } +SelectorNameId *Control::selectorNameId(Name *const *names, + unsigned nameCount, + bool hasArguments) +{ + std::vector<Name *> selectorNames(names, names + nameCount); + return d->findOrInsertSelectorNameId(selectorNames, hasArguments); +} + + VoidType *Control::voidType() { return &d->voidType; } diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h index a9b85b7baee8d44e5c520847af7c19baa738def2..5e90e0947b9e68825f80893e78983a780c5d74ec 100644 --- a/src/shared/cplusplus/Control.h +++ b/src/shared/cplusplus/Control.h @@ -89,6 +89,10 @@ public: unsigned nameCount, bool isGlobal = false); + SelectorNameId *selectorNameId(Name *const *names, + unsigned nameCount, + bool hasArguments); + /// Returns a Type object of type VoidType. VoidType *voidType(); diff --git a/src/shared/cplusplus/Name.cpp b/src/shared/cplusplus/Name.cpp index b3c9019f7d98c1eadffd97df245fb90354f9d847..7420bd496bd7562cdc21c2e0768d971f8ac1a1e4 100644 --- a/src/shared/cplusplus/Name.cpp +++ b/src/shared/cplusplus/Name.cpp @@ -76,6 +76,9 @@ bool Name::isConversionNameId() const bool Name::isQualifiedNameId() const { return asQualifiedNameId() != 0; } +bool Name::isSelectorNameId() const +{ return asSelectorNameId() != 0; } + void Name::accept(NameVisitor *visitor) { if (visitor->preVisit(this)) diff --git a/src/shared/cplusplus/Name.h b/src/shared/cplusplus/Name.h index 145b3344b986279dd753fc3dc8d387c9d1768558..3604aca570a7909f981e14f2d08a1b119ad4951a 100644 --- a/src/shared/cplusplus/Name.h +++ b/src/shared/cplusplus/Name.h @@ -71,6 +71,7 @@ public: bool isOperatorNameId() const; bool isConversionNameId() const; bool isQualifiedNameId() const; + bool isSelectorNameId() const; virtual const NameId *asNameId() const { return 0; } virtual const TemplateNameId *asTemplateNameId() const { return 0; } @@ -78,6 +79,7 @@ public: virtual const OperatorNameId *asOperatorNameId() const { return 0; } virtual const ConversionNameId *asConversionNameId() const { return 0; } virtual const QualifiedNameId *asQualifiedNameId() const { return 0; } + virtual const SelectorNameId *asSelectorNameId() const { return 0; } virtual NameId *asNameId() { return 0; } virtual TemplateNameId *asTemplateNameId() { return 0; } @@ -85,6 +87,7 @@ public: virtual OperatorNameId *asOperatorNameId() { return 0; } virtual ConversionNameId *asConversionNameId() { return 0; } virtual QualifiedNameId *asQualifiedNameId() { return 0; } + virtual SelectorNameId *asSelectorNameId() { return 0; } virtual bool isEqualTo(const Name *other) const = 0; diff --git a/src/shared/cplusplus/NameVisitor.h b/src/shared/cplusplus/NameVisitor.h index 1892137563208c00a2b94914c45bc065080ebad5..16ba837d6454a1ed10f49d5b4d6e7c9ec83b247d 100644 --- a/src/shared/cplusplus/NameVisitor.h +++ b/src/shared/cplusplus/NameVisitor.h @@ -74,6 +74,7 @@ public: virtual void visit(OperatorNameId *) {} virtual void visit(ConversionNameId *) {} virtual void visit(QualifiedNameId *) {} + virtual void visit(SelectorNameId *) {} }; CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Names.cpp b/src/shared/cplusplus/Names.cpp index 3dafad910b21bb5bac3982c3da35eb266eba54e2..32762841b6fc027cfc89a4cb734e48c6c2311412 100644 --- a/src/shared/cplusplus/Names.cpp +++ b/src/shared/cplusplus/Names.cpp @@ -268,5 +268,62 @@ bool ConversionNameId::isEqualTo(const Name *other) const return _type.isEqualTo(c->type()); } +SelectorNameId::SelectorNameId(Name *const names[], + unsigned nameCount, + bool hasArguments) + : _names(0), + _nameCount(nameCount), + _hasArguments(hasArguments) +{ + if (_nameCount) { + _names = new Name *[_nameCount]; + std::copy(&names[0], &names[nameCount], _names); + } +} + +SelectorNameId::~SelectorNameId() +{ delete[] _names; } + +void SelectorNameId::accept0(NameVisitor *visitor) +{ visitor->visit(this); } + +Identifier *SelectorNameId::identifier() const +{ + // FIXME: (EV) + return nameAt(0)->identifier(); +} + +unsigned SelectorNameId::nameCount() const +{ return _nameCount; } + +Name *SelectorNameId::nameAt(unsigned index) const +{ return _names[index]; } + +Name *const *SelectorNameId::names() const +{ return _names; } + +bool SelectorNameId::hasArguments() const +{ return _hasArguments; } + +bool SelectorNameId::isEqualTo(const Name *other) const +{ + const SelectorNameId *q = other->asSelectorNameId(); + if (! q) + return false; + else if (hasArguments() != q->hasArguments()) + return false; + else { + const unsigned count = nameCount(); + if (count != q->nameCount()) + return false; + for (unsigned i = 0; i < count; ++i) { + Name *l = nameAt(i); + Name *r = q->nameAt(i); + if (! l->isEqualTo(r)) + return false; + } + } + return true; +} CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Names.h b/src/shared/cplusplus/Names.h index c5758ba73843be7186652b8efa208dca21e2b283..b0dc395630156b0c361053704665e02df04749bd 100644 --- a/src/shared/cplusplus/Names.h +++ b/src/shared/cplusplus/Names.h @@ -271,6 +271,39 @@ private: FullySpecifiedType _type; }; +class CPLUSPLUS_EXPORT SelectorNameId: public Name +{ +public: + SelectorNameId(Name *const names[], + unsigned nameCount, + bool hasArguments); + virtual ~SelectorNameId(); + + virtual Identifier *identifier() const; + + unsigned nameCount() const; + Name *nameAt(unsigned index) const; + Name *const *names() const; + + bool hasArguments() const; + + virtual bool isEqualTo(const Name *other) const; + + virtual const SelectorNameId *asSelectorNameId() const + { return this; } + + virtual SelectorNameId *asSelectorNameId() + { return this; } + +protected: + virtual void accept0(NameVisitor *visitor); + +private: + Name **_names; + unsigned _nameCount; + bool _hasArguments; +}; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index d0a7b05bcbec271a88b938d21f5453af839a9dbf..ee8e714f64e1d39036ef02b491c306a810405b09 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -2967,7 +2967,7 @@ bool Parser::parseObjCMessageExpression(ExpressionAST *&node) ast->lbracket_token = consumeToken(); parseObjCMessageReceiver(ast->receiver_expression); - parseObjCMessageArguments(ast->argument_list); + parseObjCMessageArguments(ast->selector, ast->argument_list); match(T_RBRACKET, &(ast->rbracket_token)); node = ast; @@ -2979,25 +2979,34 @@ bool Parser::parseObjCMessageReceiver(ExpressionAST *&node) return parseExpression(node); } -bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& node) +bool Parser::parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode) { if (LA() == T_RBRACKET) return false; // nothing to do. unsigned start = cursor(); - ObjCMessageArgumentListAST *ast = new (_pool) ObjCMessageArgumentListAST; - ObjCMessageArgumentAST *argument = 0; + ObjCSelectorArgumentAST *selectorArgument = 0; + ObjCMessageArgumentAST *messageArgument = 0; - if (parseObjCSelectorArg(argument)) { - ast->arg = argument; - ObjCMessageArgumentListAST *lastArgument = ast; + if (parseObjCSelectorArg(selectorArgument, messageArgument)) { + ObjCSelectorArgumentListAST *selAst = new (_pool) ObjCSelectorArgumentListAST; + selAst->argument = selectorArgument; + ObjCSelectorArgumentListAST *lastSelector = selAst; - while (parseObjCSelectorArg(argument)) { + ObjCMessageArgumentListAST *argAst = new (_pool) ObjCMessageArgumentListAST; + argAst->arg = messageArgument; + ObjCMessageArgumentListAST *lastArgument = argAst; + + while (parseObjCSelectorArg(selectorArgument, messageArgument)) { // accept the selector args. + lastSelector->next = new (_pool) ObjCSelectorArgumentListAST; + lastSelector = lastSelector->next; + lastSelector->argument = selectorArgument; + lastArgument->next = new (_pool) ObjCMessageArgumentListAST; lastArgument = lastArgument->next; - lastArgument->arg = argument; + lastArgument->arg = messageArgument; } if (LA() == T_COMMA) { @@ -3011,17 +3020,24 @@ bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& node) lastExpression = &(binaryExpression->right_expression); } } + + ObjCSelectorWithArgumentsAST *selWithArgs = new (_pool) ObjCSelectorWithArgumentsAST; + selWithArgs->selector_arguments = selAst; + + selNode = selWithArgs; + argNode = argAst; } else { rewind(start); - ast->arg = new (_pool) ObjCMessageArgumentAST; - parseObjCSelector(ast->arg->parameter_key_identifier); + ObjCSelectorWithoutArgumentsAST *sel = new (_pool) ObjCSelectorWithoutArgumentsAST; + parseObjCSelector(sel->name_token); + selNode = sel; + argNode = 0; } - node = ast; return true; } -bool Parser::parseObjCSelectorArg(ObjCMessageArgumentAST *&node) +bool Parser::parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode) { unsigned selector_token = 0; if (!parseObjCSelector(selector_token)) @@ -3030,12 +3046,12 @@ bool Parser::parseObjCSelectorArg(ObjCMessageArgumentAST *&node) if (LA() != T_COLON) return false; - ObjCMessageArgumentAST *argument = new (_pool) ObjCMessageArgumentAST; - argument->parameter_key_identifier = selector_token; - argument->colon_token = consumeToken(); + selNode = new (_pool) ObjCSelectorArgumentAST; + selNode->name_token = selector_token; + selNode->colon_token = consumeToken(); - parseAssignmentExpression(argument->parameter_value_expression); - node = argument; + argNode = new (_pool) ObjCMessageArgumentAST; + parseAssignmentExpression(argNode->parameter_value_expression); return true; } diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index ec40707613da10f481d046789bbd0a94f75e41c6..181e4b6b712fb735dfd293b8e1b3323a3eb857d0 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -226,8 +226,8 @@ public: bool parseObjCMethodSignature(); bool parseObjCMessageExpression(ExpressionAST *&node); bool parseObjCMessageReceiver(ExpressionAST *&node); - bool parseObjCMessageArguments(ObjCMessageArgumentListAST *&node); - bool parseObjCSelectorArg(ObjCMessageArgumentAST *&node); + bool parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode); + bool parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode); bool parseObjCMethodDefinitionList(DeclarationListAST *&node); bool parseObjCMethodDefinition(DeclarationAST *&node);