From e5377519d63620a6321278249f330d9a6f2baf04 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Thu, 16 Jul 2009 11:27:45 +0200
Subject: [PATCH] Added varargs parsing for ObjC send_msg arguments.

---
 src/shared/cplusplus/Parser.cpp | 70 +++++++++++++++++++++++----------
 src/shared/cplusplus/Parser.h   |  4 +-
 2 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index cf091cfa0e0..ba705f9551b 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -2892,7 +2892,8 @@ bool Parser::parseObjCSelectorExpression(ExpressionAST *&)
     }
 
     while (lookAtObjCSelector()) {
-        parseObjCSelector();
+        unsigned selector_token = 0;
+        parseObjCSelector(selector_token);
         if (LA() == T_COLON)
             consumeToken();
         else {
@@ -2927,49 +2928,73 @@ bool Parser::parseObjCMessageReceiver(ExpressionAST *&node)
     return parseExpression(node);
 }
 
-bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& /*node*/)
+bool Parser::parseObjCMessageArguments(ObjCMessageArgumentListAST *& node)
 {
     if (LA() == T_RBRACKET)
         return false; // nothing to do.
 
     unsigned start = cursor();
 
-    if (parseObjCSelectorArgs()) {
-        while (parseObjCSelectorArgs()) {
+    ObjCMessageArgumentListAST *ast = new (_pool) ObjCMessageArgumentListAST;
+    ObjCMessageArgumentAST *argument = 0;
+
+    if (parseObjCSelectorArg(argument)) {
+        ast->arg = argument;
+        ObjCMessageArgumentListAST *lastArgument = ast;
+
+        while (parseObjCSelectorArg(argument)) {
             // accept the selector args.
+            lastArgument->next = new (_pool) ObjCMessageArgumentListAST;
+            lastArgument = lastArgument->next;
+            lastArgument->arg = argument;
+        }
+
+        if (LA() == T_COMMA) {
+            ExpressionAST **lastExpression = &(lastArgument->arg->parameter_value_expression);
+
+            while (LA() == T_COMMA) {
+                BinaryExpressionAST *binaryExpression = new (_pool) BinaryExpressionAST;
+                binaryExpression->left_expression = *lastExpression;
+                binaryExpression->binary_op_token = consumeToken(); // T_COMMA
+                parseAssignmentExpression(binaryExpression->right_expression);
+                lastExpression = &(binaryExpression->right_expression);
+            }
         }
     } else {
         rewind(start);
-        parseObjCSelector();
+        ast->arg = new (_pool) ObjCMessageArgumentAST;
+        parseObjCSelector(ast->arg->parameter_key_identifier);
     }
 
-    while (LA() == T_COMMA) {
-        consumeToken(); // skip T_COMMA
-        ExpressionAST *expression = 0;
-        parseAssignmentExpression(expression);
-    }
+    node = ast;
     return true;
 }
 
-bool Parser::parseObjCSelectorArgs()
+bool Parser::parseObjCSelectorArg(ObjCMessageArgumentAST *&node)
 {
-    parseObjCSelector();
+    unsigned selector_token = 0;
+    if (!parseObjCSelector(selector_token))
+        return false;
+
     if (LA() != T_COLON)
         return false;
 
-    /*unsigned colon_token = */consumeToken();
+    ObjCMessageArgumentAST *argument = new (_pool) ObjCMessageArgumentAST;
+    argument->parameter_key_identifier = selector_token;
+    argument->colon_token = consumeToken();
 
-    ExpressionAST *expression = 0;
-    parseAssignmentExpression(expression);
+    parseAssignmentExpression(argument->parameter_value_expression);
+    node = argument;
     return true;
 }
 
 bool Parser::parseObjCMethodSignature()
 {
-    if (parseObjCSelector()) {
+    unsigned selector_token = 0;
+    if (parseObjCSelector(selector_token)) {
         while (LA() == T_COMMA) {
             consumeToken(); // skip T_COMMA
-            parseObjCSelector();
+            parseObjCSelector(selector_token);
         }
         return true;
     }
@@ -4325,6 +4350,8 @@ bool Parser::parseObjCMethodPrototype()
 
     parseObjCTypeName();
 
+    unsigned selector_token = 0;
+
     if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) {
         while (parseObjCKeywordDeclaration()) {
         }
@@ -4341,7 +4368,7 @@ bool Parser::parseObjCMethodPrototype()
             parseParameterDeclaration(parameter_declaration);
         }
     } else if (lookAtObjCSelector()) {
-        parseObjCSelector();
+        parseObjCSelector(selector_token);
     } else {
         _translationUnit->error(cursor(), "expected a selector");
     }
@@ -4396,12 +4423,12 @@ bool Parser::parseObjCTypeName()
 
 // objc-selector ::= T_IDENTIFIER | keyword
 //
-bool Parser::parseObjCSelector()
+bool Parser::parseObjCSelector(unsigned &selector_token)
 {
     if (! lookAtObjCSelector())
         return false;
 
-    consumeToken();
+    selector_token = consumeToken();
     return true;
 }
 
@@ -4412,7 +4439,8 @@ bool Parser::parseObjCKeywordDeclaration()
     if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON)))
         return false;
 
-    parseObjCSelector();
+    unsigned selector_token = 0;
+    parseObjCSelector(selector_token);
 
     unsigned colon_token = 0;
     match(T_COLON, &colon_token);
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 4d6af741bfd..c81312d94f9 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -227,7 +227,7 @@ public:
     bool parseObjCMessageExpression(ExpressionAST *&node);
     bool parseObjCMessageReceiver(ExpressionAST *&node);
     bool parseObjCMessageArguments(ObjCMessageArgumentListAST *&node);
-    bool parseObjCSelectorArgs();
+    bool parseObjCSelectorArg(ObjCMessageArgumentAST *&node);
     bool parseObjCMethodDefinitionList();
     bool parseObjCMethodDefinition();
 
@@ -241,7 +241,7 @@ public:
     bool parseObjCMethodPrototype();
     bool parseObjCPropertyAttribute();
     bool parseObjCTypeName();
-    bool parseObjCSelector();
+    bool parseObjCSelector(unsigned &selector_token);
     bool parseObjCKeywordDeclaration();
     bool parseObjCTypeQualifiers();
     bool parseObjCEnd(DeclarationAST *&node);
-- 
GitLab