From fd90c3503db076b95f2e97455e9e8fcf9c374a88 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Thu, 4 Feb 2010 14:55:18 +0100
Subject: [PATCH] Added AST nodes for compound expressions (a GNU extension).

---
 src/libs/cplusplus/ResolveExpression.cpp |  5 ++++
 src/libs/cplusplus/ResolveExpression.h   |  1 +
 src/shared/cplusplus/AST.cpp             | 16 +++++++++--
 src/shared/cplusplus/AST.h               | 21 ++++++++++++++
 src/shared/cplusplus/ASTClone.cpp        | 10 +++++++
 src/shared/cplusplus/ASTMatch0.cpp       |  8 ++++++
 src/shared/cplusplus/ASTMatcher.cpp      | 17 +++++++++++
 src/shared/cplusplus/ASTMatcher.h        |  1 +
 src/shared/cplusplus/ASTVisit.cpp        |  8 ++++++
 src/shared/cplusplus/ASTVisitor.h        |  2 ++
 src/shared/cplusplus/ASTfwd.h            |  1 +
 src/shared/cplusplus/CheckExpression.cpp |  5 ++++
 src/shared/cplusplus/CheckExpression.h   |  1 +
 src/shared/cplusplus/Parser.cpp          | 36 +++++++++++-------------
 14 files changed, 111 insertions(+), 21 deletions(-)

diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index fe06d3dabfa..c6f8bd4b5b8 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -293,6 +293,11 @@ bool ResolveExpression::visit(ThisExpressionAST *)
     return false;
 }
 
+bool ResolveExpression::visit(CompoundExpressionAST *ast)
+{
+    return true; // ###
+}
+
 bool ResolveExpression::visit(NestedExpressionAST *ast)
 {
     accept(ast->expression);
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 1d613228d83..3a367964223 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -93,6 +93,7 @@ protected:
     virtual bool visit(TypeIdAST *ast);
     virtual bool visit(UnaryExpressionAST *ast);
     virtual bool visit(CompoundLiteralAST *ast);
+    virtual bool visit(CompoundExpressionAST *ast);
 
     //names
     virtual bool visit(QualifiedNameAST *ast);
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index fe697ea91de..a6f5bfb674e 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -326,6 +326,20 @@ unsigned BoolLiteralAST::lastToken() const
     return literal_token + 1;
 }
 
+unsigned CompoundExpressionAST::firstToken() const
+{
+    return lparen_token;
+}
+
+unsigned CompoundExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    else if (compoundStatement)
+        return compoundStatement->lastToken();
+    else
+        return lparen_token + 1;
+}
 
 unsigned CompoundLiteralAST::firstToken() const
 {
@@ -2300,5 +2314,3 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const
     if (lparen_token) return lparen_token + 1;
     return synchronized_token + 1;
 }
-
-
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 19239f32d9c..c719f311608 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -161,6 +161,7 @@ public:
     virtual CastExpressionAST *asCastExpression() { return 0; }
     virtual CatchClauseAST *asCatchClause() { return 0; }
     virtual ClassSpecifierAST *asClassSpecifier() { return 0; }
+    virtual CompoundExpressionAST *asCompoundExpression() { return 0; }
     virtual CompoundLiteralAST *asCompoundLiteral() { return 0; }
     virtual CompoundStatementAST *asCompoundStatement() { return 0; }
     virtual ConditionAST *asCondition() { return 0; }
@@ -700,6 +701,26 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
+class CPLUSPLUS_EXPORT CompoundExpressionAST: public ExpressionAST
+{
+public:
+    unsigned lparen_token;
+    CompoundStatementAST *compoundStatement;
+    unsigned rparen_token;
+
+public:
+    virtual CompoundExpressionAST *asCompoundExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual CompoundExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
 class CPLUSPLUS_EXPORT CompoundLiteralAST: public ExpressionAST
 {
 public:
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index a3bb26e7d68..b794a8b4b12 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -213,6 +213,16 @@ BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+CompoundExpressionAST *CompoundExpressionAST::clone(MemoryPool *pool) const
+{
+    CompoundExpressionAST *ast = new (pool) CompoundExpressionAST;
+    ast->lparen_token = lparen_token;
+    if (compoundStatement)
+        ast->compoundStatement = compoundStatement->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 CompoundLiteralAST *CompoundLiteralAST::clone(MemoryPool *pool) const
 {
     CompoundLiteralAST *ast = new (pool) CompoundLiteralAST;
diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp
index 807bfbf4d04..f1d47aaa8a2 100644
--- a/src/shared/cplusplus/ASTMatch0.cpp
+++ b/src/shared/cplusplus/ASTMatch0.cpp
@@ -153,6 +153,14 @@ bool BaseSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
     return false;
 }
 
+bool CompoundExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (CompoundExpressionAST *_other = pattern->asCompoundExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
 bool CompoundLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
 {
     if (CompoundLiteralAST *_other = pattern->asCompoundLiteral())
diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp
index febb9e5fe2a..aa1a0f3ba62 100644
--- a/src/shared/cplusplus/ASTMatcher.cpp
+++ b/src/shared/cplusplus/ASTMatcher.cpp
@@ -331,6 +331,23 @@ bool ASTMatcher::match(BaseSpecifierAST *node, BaseSpecifierAST *pattern)
     return true;
 }
 
+bool ASTMatcher::match(CompoundExpressionAST *node, CompoundExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->compoundStatement)
+        pattern->compoundStatement = node->compoundStatement;
+    else if (! AST::match(node->compoundStatement, pattern->compoundStatement, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
 bool ASTMatcher::match(CompoundLiteralAST *node, CompoundLiteralAST *pattern)
 {
     (void) node;
diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h
index df3aa6cf5a9..c8263ab2377 100644
--- a/src/shared/cplusplus/ASTMatcher.h
+++ b/src/shared/cplusplus/ASTMatcher.h
@@ -59,6 +59,7 @@ public:
     virtual bool match(CastExpressionAST *node, CastExpressionAST *pattern);
     virtual bool match(CatchClauseAST *node, CatchClauseAST *pattern);
     virtual bool match(ClassSpecifierAST *node, ClassSpecifierAST *pattern);
+    virtual bool match(CompoundExpressionAST *node, CompoundExpressionAST *pattern);
     virtual bool match(CompoundLiteralAST *node, CompoundLiteralAST *pattern);
     virtual bool match(CompoundStatementAST *node, CompoundStatementAST *pattern);
     virtual bool match(ConditionAST *node, ConditionAST *pattern);
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 5a563778fbb..0d7d7fee19f 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -153,6 +153,14 @@ void BaseSpecifierAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void CompoundExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(compoundStatement, visitor);
+    }
+    visitor->endVisit(this);
+}
+
 void CompoundLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index 4c80732cd6f..2e10093c5bc 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -122,6 +122,7 @@ public:
     virtual bool visit(CastExpressionAST *) { return true; }
     virtual bool visit(CatchClauseAST *) { return true; }
     virtual bool visit(ClassSpecifierAST *) { return true; }
+    virtual bool visit(CompoundExpressionAST *) { return true; }
     virtual bool visit(CompoundLiteralAST *) { return true; }
     virtual bool visit(CompoundStatementAST *) { return true; }
     virtual bool visit(ConditionAST *) { return true; }
@@ -252,6 +253,7 @@ public:
     virtual void endVisit(CastExpressionAST *) { }
     virtual void endVisit(CatchClauseAST *) { }
     virtual void endVisit(ClassSpecifierAST *) { }
+    virtual void endVisit(CompoundExpressionAST *) { }
     virtual void endVisit(CompoundLiteralAST *) { }
     virtual void endVisit(CompoundStatementAST *) { }
     virtual void endVisit(ConditionAST *) { }
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index 722e36907a3..13a02c0e5cf 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -75,6 +75,7 @@ class CaseStatementAST;
 class CastExpressionAST;
 class CatchClauseAST;
 class ClassSpecifierAST;
+class CompoundExpressionAST;
 class CompoundLiteralAST;
 class CompoundStatementAST;
 class ConditionAST;
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index f8da07534c5..c971204c2e4 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -287,6 +287,11 @@ bool CheckExpression::visit(ThisExpressionAST *)
     return false;
 }
 
+bool CheckExpression::visit(CompoundExpressionAST *ast)
+{
+    return true; // ###
+}
+
 bool CheckExpression::visit(NestedExpressionAST *ast)
 {
     FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h
index 8085731df5d..9cc1722d7c2 100644
--- a/src/shared/cplusplus/CheckExpression.h
+++ b/src/shared/cplusplus/CheckExpression.h
@@ -94,6 +94,7 @@ protected:
     virtual bool visit(UnaryExpressionAST *ast);
     virtual bool visit(QtMethodAST *ast);
     virtual bool visit(CompoundLiteralAST *ast);
+    virtual bool visit(CompoundExpressionAST *ast);
 
     //names
     virtual bool visit(QualifiedNameAST *ast);
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index de66dbfac82..84a92a186aa 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -3437,7 +3437,19 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node)
         return parseThisExpression(node);
 
     case T_LPAREN:
-        return parseNestedExpression(node);
+        if (LA(2) == T_LBRACE) {
+            // GNU extension: '(' '{' statement-list '}' ')'
+            CompoundExpressionAST *ast = new (_pool) CompoundExpressionAST;
+            ast->lparen_token = consumeToken();
+            StatementAST *statement = 0;
+            parseCompoundStatement(statement);
+            ast->compoundStatement = statement->asCompoundStatement();
+            match(T_RPAREN, &ast->rparen_token);
+            node = ast;
+            return true;
+        } else {
+            return parseNestedExpression(node);
+        }
 
     case T_SIGNAL:
     case T_SLOT:
@@ -3799,19 +3811,6 @@ bool Parser::parseNestedExpression(ExpressionAST *&node)
     DEBUG_THIS_RULE();
     if (LA() == T_LPAREN) {
         unsigned lparen_token = consumeToken();
-
-        if (LA() == T_LBRACE) {
-            NestedExpressionAST *ast = new (_pool) NestedExpressionAST;
-            ast->lparen_token = lparen_token;
-
-            // ### ast
-            StatementAST *statement = 0;
-            parseCompoundStatement(statement);
-            match(T_RPAREN, &ast->rparen_token);
-            node = ast;
-            return true;
-        }
-
         bool previousTemplateArguments = switchTemplateArguments(false);
 
         ExpressionAST *expression = 0;
@@ -5275,12 +5274,11 @@ bool Parser::parseObjCContextKeyword(int kind, unsigned &in_token)
 {
     DEBUG_THIS_RULE();
 
-    if (peekAtObjCContextKeyword(kind)) {
-        in_token = consumeToken();
-        return true;
-    } else {
+    if (!peekAtObjCContextKeyword(kind))
         return false;
-    }
+
+    in_token = consumeToken();
+    return true;
 }
 
 
-- 
GitLab