From da817310c2c07a107d21e743370a09d4adfc4852 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Wed, 23 Jun 2010 14:38:41 +0200
Subject: [PATCH] Get rid of PostfixExpressionAST and store the base expression
 together with the PostfixAST nodes.

---
 src/libs/cplusplus/FindUsages.cpp        | 17 +----
 src/libs/cplusplus/FindUsages.h          |  3 -
 src/libs/cplusplus/ResolveExpression.cpp | 24 ++----
 src/libs/cplusplus/ResolveExpression.h   |  1 -
 src/plugins/cppeditor/cppeditor.cpp      | 10 +--
 src/plugins/cppeditor/cppquickfix.cpp    | 95 ++++++++++--------------
 src/shared/cplusplus/AST.cpp             | 38 ++++++----
 src/shared/cplusplus/AST.h               | 43 ++++-------
 src/shared/cplusplus/ASTClone.cpp        | 19 ++---
 src/shared/cplusplus/ASTMatch0.cpp       |  8 --
 src/shared/cplusplus/ASTMatcher.cpp      | 38 +++++-----
 src/shared/cplusplus/ASTMatcher.h        |  1 -
 src/shared/cplusplus/ASTPatternBuilder.h |  7 --
 src/shared/cplusplus/ASTVisit.cpp        | 13 +---
 src/shared/cplusplus/ASTVisitor.h        |  2 -
 src/shared/cplusplus/ASTfwd.h            |  1 -
 src/shared/cplusplus/CheckExpression.cpp | 18 ++---
 src/shared/cplusplus/CheckExpression.h   |  1 -
 src/shared/cplusplus/Parser.cpp          | 24 ++----
 19 files changed, 132 insertions(+), 231 deletions(-)

diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 190168f919c..f8119fe456f 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -194,27 +194,12 @@ bool FindUsages::visit(MemInitializerAST *ast)
     return false;
 }
 
-bool FindUsages::visit(PostfixExpressionAST *ast)
-{
-    _postfixExpressionStack.append(ast);
-    return true;
-}
-
-void FindUsages::endVisit(PostfixExpressionAST *)
-{
-    _postfixExpressionStack.removeLast();
-}
-
 bool FindUsages::visit(MemberAccessAST *ast)
 {
     if (ast->member_name) {
         if (SimpleNameAST *simple = ast->member_name->asSimpleName()) {
             if (identifier(simple->identifier_token) == _id) {
-                Q_ASSERT(! _postfixExpressionStack.isEmpty());
-
-                checkExpression(_postfixExpressionStack.last()->firstToken(),
-                                simple->identifier_token);
-
+                checkExpression(ast->firstToken(), simple->identifier_token);
                 return false;
             }
         }
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index d2809db995a..ff7a3b063be 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -83,8 +83,6 @@ protected:
     void ensureNameIsValid(NameAST *ast);
 
     virtual bool visit(MemInitializerAST *ast);
-    virtual bool visit(PostfixExpressionAST *ast);
-    virtual void endVisit(PostfixExpressionAST *);
     virtual bool visit(MemberAccessAST *ast);
     virtual bool visit(QualifiedNameAST *ast);
     virtual bool visit(EnumeratorAST *ast);
@@ -116,7 +114,6 @@ private:
     QByteArray _source;
     Document::Ptr _exprDoc;
     Semantic _sem;
-    QList<PostfixExpressionAST *> _postfixExpressionStack;
     QList<QualifiedNameAST *> _qualifiedNameStack;
     QList<TemplateDeclarationAST *> _templateDeclarationStack;
     QList<int> _references;
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 22def6967c3..3f145979f3b 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -244,16 +244,6 @@ bool ResolveExpression::visit(TypeConstructorCallAST *)
     return false;
 }
 
-bool ResolveExpression::visit(PostfixExpressionAST *ast)
-{
-    accept(ast->base_expression);
-
-    for (PostfixListAST *it = ast->postfix_expression_list; it; it = it->next)
-        accept(it->value);
-
-    return false;
-}
-
 bool ResolveExpression::visit(SizeofExpressionAST *)
 {
     FullySpecifiedType ty(control()->integerType(IntegerType::Int));
@@ -468,8 +458,7 @@ bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgu
 
 bool ResolveExpression::visit(CallAST *ast)
 {
-    const QList<LookupItem> baseResults = _results;
-    _results.clear();
+    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
 
     // Compute the types of the actual arguments.
     int actualArgumentCount = 0;
@@ -514,9 +503,7 @@ bool ResolveExpression::visit(CallAST *ast)
 
 bool ResolveExpression::visit(ArrayAccessAST *ast)
 {
-    const QList<LookupItem> baseResults = _results;
-    _results.clear();
-
+    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
     const QList<LookupItem> indexResults = resolve(ast->expression);
 
     const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
@@ -551,8 +538,7 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
 {
     // The candidate types for the base expression are stored in
     // _results.
-    const QList<LookupItem> baseResults = _results;
-    _results.clear();
+    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
 
     // Evaluate the expression-id that follows the access operator.
     const Name *memberName = 0;
@@ -644,8 +630,10 @@ FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol
     return DeprecatedGenTemplateInstance::instantiate(className, candidate, _context.control());
 }
 
-bool ResolveExpression::visit(PostIncrDecrAST *)
+bool ResolveExpression::visit(PostIncrDecrAST *ast)
 {
+    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
+    _results = baseResults;
     return false;
 }
 
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index 830b210815d..8496631af4c 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -79,7 +79,6 @@ protected:
     virtual bool visit(TypeidExpressionAST *ast);
     virtual bool visit(TypenameCallExpressionAST *ast);
     virtual bool visit(TypeConstructorCallAST *ast);
-    virtual bool visit(PostfixExpressionAST *ast);
     virtual bool visit(SizeofExpressionAST *ast);
     virtual bool visit(NumericLiteralAST *ast);
     virtual bool visit(BoolLiteralAST *ast);
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 2fba70c6dee..a078ee72ff4 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -346,15 +346,11 @@ protected:
         return false;
     }
 
-    virtual bool visit(PostfixExpressionAST *ast)
+    virtual bool visit(MemberAccessAST *ast)
     {
+        // accept only the base expression
         accept(ast->base_expression);
-        for (PostfixListAST *it = ast->postfix_expression_list; it; it = it->next) {
-            PostfixAST *fx = it->value;
-            if (fx->asMemberAccess() != 0)
-                continue; // skip members
-            accept(fx);
-        }
+        // and ignore the member name.
         return false;
     }
 
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index b0dadc82601..f4baa732995 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -783,40 +783,32 @@ public:
 
     virtual int match(const QList<AST *> &path)
     {
+        stringLiteral = 0;
+        isObjCStringLiteral = false;
+
         if (path.isEmpty())
-            return -1;
+            return -1; // nothing to do
 
-        int index = path.size() - 1;
-        stringLiteral = path[index]->asStringLiteral();
+        stringLiteral = path.last()->asStringLiteral();
 
-        if (!stringLiteral)
+        if (! stringLiteral)
             return -1;
 
-        isObjCStringLiteral = charAt(startOf(stringLiteral)) == QLatin1Char('@');
-
-        // check if it is already wrapped in QLatin1String or -Literal
-        if (index-2 < 0)
-            return index;
+        else if (path.size() > 1) {
+            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
+                if (call->base_expression) {
+                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
+                        const QByteArray id(tokenAt(functionName->identifier_token).identifier->chars());
 
-        CallAST *call = path[index-1]->asCall();
-        PostfixExpressionAST *postfixExp = path[index-2]->asPostfixExpression();
-        if (call && postfixExp
-            && postfixExp->base_expression
-            && postfixExp->postfix_expression_list
-            && postfixExp->postfix_expression_list->value == call)
-        {
-            NameAST *callName = postfixExp->base_expression->asName();
-            if (!callName)
-                return index;
-
-            QByteArray callNameString(tokenAt(callName->firstToken()).spell());
-            if (callNameString == "QLatin1String"
-                || callNameString == "QLatin1Literal"
-                )
-                return -1;
+                        if (id == "QLatin1String" || id == "QLatin1Literal")
+                            return -1; // skip it
+                    }
+                }
+            }
         }
 
-        return index;
+        isObjCStringLiteral = charAt(startOf(stringLiteral)) == QLatin1Char('@');
+        return path.size() - 1; // very high priority
     }
 
     virtual void createChanges()
@@ -845,7 +837,9 @@ class CStringToNSString: public CppQuickFixOperation
 {
 public:
     CStringToNSString(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), stringLiteral(0), qlatin1Call(0)
+        : CppQuickFixOperation(editor)
+        , stringLiteral(0)
+        , qlatin1Call(0)
     {}
 
     virtual QString description() const
@@ -855,43 +849,34 @@ public:
 
     virtual int match(const QList<AST *> &path)
     {
+        stringLiteral = 0;
+        qlatin1Call = 0;
+
         if (path.isEmpty())
-            return -1;
+            return -1; // nothing to do
 
-        int index = path.size() - 1;
-        stringLiteral = path[index]->asStringLiteral();
+        stringLiteral = path.last()->asStringLiteral();
 
-        if (!stringLiteral)
+        if (! stringLiteral)
             return -1;
 
-        if (charAt(startOf(stringLiteral)) == QLatin1Char('@'))
-            return -1;
+        else if (charAt(startOf(stringLiteral)) == QLatin1Char('@'))
+            return -1; // it's already an objc string literal.
 
-        // check if it is already wrapped in QLatin1String or -Literal
-        if (index-2 < 0)
-            return index;
-
-        CallAST *call = path[index-1]->asCall();
-        PostfixExpressionAST *postfixExp = path[index-2]->asPostfixExpression();
-        if (call && postfixExp
-            && postfixExp->base_expression
-            && postfixExp->postfix_expression_list
-            && postfixExp->postfix_expression_list->value == call)
-        {
-            NameAST *callName = postfixExp->base_expression->asName();
-            if (!callName)
-                return index;
+        else if (path.size() > 1) {
+            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
+                if (call->base_expression) {
+                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
+                        const QByteArray id(tokenAt(functionName->identifier_token).identifier->chars());
 
-            if (!(postfixExp->postfix_expression_list->next)) {
-                QByteArray callNameString(tokenAt(callName->firstToken()).spell());
-                if (callNameString == "QLatin1String"
-                    || callNameString == "QLatin1Literal"
-                    )
-                    qlatin1Call = postfixExp;
+                        if (id == "QLatin1String" || id == "QLatin1Literal")
+                            qlatin1Call = call;
+                    }
+                }
             }
         }
 
-        return index;
+        return path.size() - 1; // very high priority
     }
 
     virtual void createChanges()
@@ -910,7 +895,7 @@ public:
 
 private:
     StringLiteralAST *stringLiteral;
-    PostfixExpressionAST *qlatin1Call;
+    CallAST *qlatin1Call;
 };
 
 } // end of anonymous namespace
diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 85c87ec7ee3..753a2178d00 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -287,6 +287,9 @@ unsigned QtInterfacesDeclarationAST::lastToken() const
 
 unsigned ArrayAccessAST::firstToken() const
 {
+    if (base_expression)
+        return base_expression->firstToken();
+
     return lbracket_token;
 }
 
@@ -296,7 +299,9 @@ unsigned ArrayAccessAST::lastToken() const
         return rbracket_token + 1;
     else if (expression)
         return expression->lastToken();
-    return lbracket_token + 1;
+    if (lbracket_token)
+        return lbracket_token + 1;
+    return base_expression->lastToken();
 }
 
 
@@ -474,6 +479,9 @@ unsigned BreakStatementAST::lastToken() const
 
 unsigned CallAST::firstToken() const
 {
+    if (base_expression)
+        return base_expression->firstToken();
+
     return lparen_token;
 }
 
@@ -485,7 +493,10 @@ unsigned CallAST::lastToken() const
     else if (expression_list)
         return expression_list->lastToken();
 
-    return lparen_token + 1;
+    if (lparen_token)
+        return lparen_token + 1;
+
+    return base_expression->lastToken();
 }
 
 
@@ -1183,6 +1194,8 @@ unsigned MemInitializerAST::lastToken() const
 
 unsigned MemberAccessAST::firstToken() const
 {
+    if (base_expression)
+        return base_expression->firstToken();
     return access_token;
 }
 
@@ -1192,7 +1205,9 @@ unsigned MemberAccessAST::lastToken() const
         return member_name->lastToken();
     else if (template_token)
         return template_token + 1;
-    return access_token + 1;
+    else if (access_token)
+        return access_token + 1;
+    return base_expression->lastToken();
 }
 
 
@@ -1488,24 +1503,15 @@ unsigned PointerToMemberAST::lastToken() const
 
 unsigned PostIncrDecrAST::firstToken() const
 {
+    if (base_expression)
+        return base_expression->firstToken();
     return incr_decr_token;
 }
 
 unsigned PostIncrDecrAST::lastToken() const
 {
-    return incr_decr_token + 1;
-}
-
-
-unsigned PostfixExpressionAST::firstToken() const
-{
-    return base_expression->firstToken();
-}
-
-unsigned PostfixExpressionAST::lastToken() const
-{
-    if (postfix_expression_list)
-        return postfix_expression_list->lastToken();
+    if (incr_decr_token)
+        return incr_decr_token + 1;
     return base_expression->lastToken();
 }
 
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index 8f90555af72..73452ae7784 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -258,7 +258,6 @@ public:
     virtual PostIncrDecrAST *asPostIncrDecr() { return 0; }
     virtual PostfixAST *asPostfix() { return 0; }
     virtual PostfixDeclaratorAST *asPostfixDeclarator() { return 0; }
-    virtual PostfixExpressionAST *asPostfixExpression() { return 0; }
     virtual PtrOperatorAST *asPtrOperator() { return 0; }
     virtual QtEnumDeclarationAST *asQtEnumDeclaration() { return 0; }
     virtual QtFlagsDeclarationAST *asQtFlagsDeclaration() { return 0; }
@@ -375,7 +374,7 @@ public:
     virtual PtrOperatorAST *clone(MemoryPool *pool) const = 0;
 };
 
-class CPLUSPLUS_EXPORT PostfixAST: public AST
+class CPLUSPLUS_EXPORT PostfixAST: public ExpressionAST
 {
 public:
     PostfixAST()
@@ -2503,13 +2502,15 @@ protected:
 class CPLUSPLUS_EXPORT CallAST: public PostfixAST
 {
 public:
+    ExpressionAST *base_expression;
     unsigned lparen_token;
     ExpressionListAST *expression_list;
     unsigned rparen_token;
 
 public:
     CallAST()
-        : lparen_token(0)
+        : base_expression(0)
+        , lparen_token(0)
         , expression_list(0)
         , rparen_token(0)
     {}
@@ -2529,13 +2530,15 @@ protected:
 class CPLUSPLUS_EXPORT ArrayAccessAST: public PostfixAST
 {
 public:
+    ExpressionAST *base_expression;
     unsigned lbracket_token;
     ExpressionAST *expression;
     unsigned rbracket_token;
 
 public:
     ArrayAccessAST()
-        : lbracket_token(0)
+        : base_expression(0)
+        , lbracket_token(0)
         , expression(0)
         , rbracket_token(0)
     {}
@@ -2555,11 +2558,13 @@ protected:
 class CPLUSPLUS_EXPORT PostIncrDecrAST: public PostfixAST
 {
 public:
+    ExpressionAST *base_expression;
     unsigned incr_decr_token;
 
 public:
     PostIncrDecrAST()
-        : incr_decr_token(0)
+        : base_expression(0)
+        , incr_decr_token(0)
     {}
 
     virtual PostIncrDecrAST *asPostIncrDecr() { return this; }
@@ -2577,13 +2582,15 @@ protected:
 class CPLUSPLUS_EXPORT MemberAccessAST: public PostfixAST
 {
 public:
+    ExpressionAST *base_expression;
     unsigned access_token;
     unsigned template_token;
     NameAST *member_name;
 
 public:
     MemberAccessAST()
-        : access_token(0)
+        : base_expression(0)
+        , access_token(0)
         , template_token(0)
         , member_name(0)
     {}
@@ -2686,30 +2693,6 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
-class CPLUSPLUS_EXPORT PostfixExpressionAST: public ExpressionAST
-{
-public:
-    ExpressionAST *base_expression;
-    PostfixListAST *postfix_expression_list;
-
-public:
-    PostfixExpressionAST()
-        : base_expression(0)
-        , postfix_expression_list(0)
-    {}
-
-    virtual PostfixExpressionAST *asPostfixExpression() { return this; }
-
-    virtual unsigned firstToken() const;
-    virtual unsigned lastToken() const;
-
-    virtual PostfixExpressionAST *clone(MemoryPool *pool) const;
-
-protected:
-    virtual void accept0(ASTVisitor *visitor);
-    virtual bool match0(AST *, ASTMatcher *);
-};
-
 class CPLUSPLUS_EXPORT PointerToMemberAST: public PtrOperatorAST
 {
 public:
diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp
index 73237e17657..2ddcfcd1264 100644
--- a/src/shared/cplusplus/ASTClone.cpp
+++ b/src/shared/cplusplus/ASTClone.cpp
@@ -928,6 +928,8 @@ ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *
 CallAST *CallAST::clone(MemoryPool *pool) const
 {
     CallAST *ast = new (pool) CallAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
     ast->lparen_token = lparen_token;
     for (ExpressionListAST *iter = expression_list, **ast_iter = &ast->expression_list;
          iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
@@ -939,6 +941,8 @@ CallAST *CallAST::clone(MemoryPool *pool) const
 ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
 {
     ArrayAccessAST *ast = new (pool) ArrayAccessAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
     ast->lbracket_token = lbracket_token;
     if (expression)
         ast->expression = expression->clone(pool);
@@ -949,6 +953,8 @@ ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
 PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
 {
     PostIncrDecrAST *ast = new (pool) PostIncrDecrAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
     ast->incr_decr_token = incr_decr_token;
     return ast;
 }
@@ -956,6 +962,8 @@ PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
 MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const
 {
     MemberAccessAST *ast = new (pool) MemberAccessAST;
+    if (base_expression)
+        ast->base_expression = base_expression->clone(pool);
     ast->access_token = access_token;
     ast->template_token = template_token;
     if (member_name)
@@ -1002,17 +1010,6 @@ TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const
     return ast;
 }
 
-PostfixExpressionAST *PostfixExpressionAST::clone(MemoryPool *pool) const
-{
-    PostfixExpressionAST *ast = new (pool) PostfixExpressionAST;
-    if (base_expression)
-        ast->base_expression = base_expression->clone(pool);
-    for (PostfixListAST *iter = postfix_expression_list, **ast_iter = &ast->postfix_expression_list;
-         iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
-        *ast_iter = new (pool) PostfixListAST((iter->value) ? iter->value->clone(pool) : 0);
-    return ast;
-}
-
 PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const
 {
     PointerToMemberAST *ast = new (pool) PointerToMemberAST;
diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp
index 0838f3e2a43..1ab0b0c077d 100644
--- a/src/shared/cplusplus/ASTMatch0.cpp
+++ b/src/shared/cplusplus/ASTMatch0.cpp
@@ -689,14 +689,6 @@ bool TypeConstructorCallAST::match0(AST *pattern, ASTMatcher *matcher)
     return false;
 }
 
-bool PostfixExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
-{
-    if (PostfixExpressionAST *_other = pattern->asPostfixExpression())
-        return matcher->match(this, _other);
-
-    return false;
-}
-
 bool PointerToMemberAST::match0(AST *pattern, ASTMatcher *matcher)
 {
     if (PointerToMemberAST *_other = pattern->asPointerToMember())
diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp
index 4be5014abd4..e0b6af2591a 100644
--- a/src/shared/cplusplus/ASTMatcher.cpp
+++ b/src/shared/cplusplus/ASTMatcher.cpp
@@ -1560,6 +1560,11 @@ bool ASTMatcher::match(CallAST *node, CallAST *pattern)
     (void) node;
     (void) pattern;
 
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
     pattern->lparen_token = node->lparen_token;
 
     if (! pattern->expression_list)
@@ -1577,6 +1582,11 @@ bool ASTMatcher::match(ArrayAccessAST *node, ArrayAccessAST *pattern)
     (void) node;
     (void) pattern;
 
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
     pattern->lbracket_token = node->lbracket_token;
 
     if (! pattern->expression)
@@ -1594,6 +1604,11 @@ bool ASTMatcher::match(PostIncrDecrAST *node, PostIncrDecrAST *pattern)
     (void) node;
     (void) pattern;
 
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
     pattern->incr_decr_token = node->incr_decr_token;
 
     return true;
@@ -1604,6 +1619,11 @@ bool ASTMatcher::match(MemberAccessAST *node, MemberAccessAST *pattern)
     (void) node;
     (void) pattern;
 
+    if (! pattern->base_expression)
+        pattern->base_expression = node->base_expression;
+    else if (! AST::match(node->base_expression, pattern->base_expression, this))
+        return false;
+
     pattern->access_token = node->access_token;
 
     pattern->template_token = node->template_token;
@@ -1681,24 +1701,6 @@ bool ASTMatcher::match(TypeConstructorCallAST *node, TypeConstructorCallAST *pat
     return true;
 }
 
-bool ASTMatcher::match(PostfixExpressionAST *node, PostfixExpressionAST *pattern)
-{
-    (void) node;
-    (void) pattern;
-
-    if (! pattern->base_expression)
-        pattern->base_expression = node->base_expression;
-    else if (! AST::match(node->base_expression, pattern->base_expression, this))
-        return false;
-
-    if (! pattern->postfix_expression_list)
-        pattern->postfix_expression_list = node->postfix_expression_list;
-    else if (! AST::match(node->postfix_expression_list, pattern->postfix_expression_list, this))
-        return false;
-
-    return true;
-}
-
 bool ASTMatcher::match(PointerToMemberAST *node, PointerToMemberAST *pattern)
 {
     (void) node;
diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h
index 71793287717..c5fff82629a 100644
--- a/src/shared/cplusplus/ASTMatcher.h
+++ b/src/shared/cplusplus/ASTMatcher.h
@@ -115,7 +115,6 @@ public:
     virtual bool match(PointerAST *node, PointerAST *pattern);
     virtual bool match(PointerToMemberAST *node, PointerToMemberAST *pattern);
     virtual bool match(PostIncrDecrAST *node, PostIncrDecrAST *pattern);
-    virtual bool match(PostfixExpressionAST *node, PostfixExpressionAST *pattern);
     virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern);
     virtual bool match(ReferenceAST *node, ReferenceAST *pattern);
     virtual bool match(ReturnStatementAST *node, ReturnStatementAST *pattern);
diff --git a/src/shared/cplusplus/ASTPatternBuilder.h b/src/shared/cplusplus/ASTPatternBuilder.h
index fe92a4808a1..3f03f99586a 100644
--- a/src/shared/cplusplus/ASTPatternBuilder.h
+++ b/src/shared/cplusplus/ASTPatternBuilder.h
@@ -531,13 +531,6 @@ public:
         return __ast;
     }
 
-    PostfixExpressionAST *PostfixExpression(ExpressionAST *base_expression = 0)
-    {
-        PostfixExpressionAST *__ast = new (&pool) PostfixExpressionAST;
-        __ast->base_expression = base_expression;
-        return __ast;
-    }
-
     PointerToMemberAST *PointerToMember()
     {
         PointerToMemberAST *__ast = new (&pool) PointerToMemberAST;
diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp
index 3c790aadb35..5a299ed53f8 100644
--- a/src/shared/cplusplus/ASTVisit.cpp
+++ b/src/shared/cplusplus/ASTVisit.cpp
@@ -680,6 +680,7 @@ void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor)
 void CallAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
+        accept(base_expression, visitor);
         accept(expression_list, visitor);
     }
     visitor->endVisit(this);
@@ -688,6 +689,7 @@ void CallAST::accept0(ASTVisitor *visitor)
 void ArrayAccessAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
+        accept(base_expression, visitor);
         accept(expression, visitor);
     }
     visitor->endVisit(this);
@@ -696,6 +698,7 @@ void ArrayAccessAST::accept0(ASTVisitor *visitor)
 void PostIncrDecrAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
+        accept(base_expression, visitor);
     }
     visitor->endVisit(this);
 }
@@ -703,6 +706,7 @@ void PostIncrDecrAST::accept0(ASTVisitor *visitor)
 void MemberAccessAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
+        accept(base_expression, visitor);
         accept(member_name, visitor);
     }
     visitor->endVisit(this);
@@ -734,15 +738,6 @@ void TypeConstructorCallAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
-void PostfixExpressionAST::accept0(ASTVisitor *visitor)
-{
-    if (visitor->visit(this)) {
-        accept(base_expression, visitor);
-        accept(postfix_expression_list, visitor);
-    }
-    visitor->endVisit(this);
-}
-
 void PointerToMemberAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h
index f5d91405608..a515da4d1bf 100644
--- a/src/shared/cplusplus/ASTVisitor.h
+++ b/src/shared/cplusplus/ASTVisitor.h
@@ -176,7 +176,6 @@ public:
     virtual bool visit(PointerAST *) { return true; }
     virtual bool visit(PointerToMemberAST *) { return true; }
     virtual bool visit(PostIncrDecrAST *) { return true; }
-    virtual bool visit(PostfixExpressionAST *) { return true; }
     virtual bool visit(QualifiedNameAST *) { return true; }
     virtual bool visit(ReferenceAST *) { return true; }
     virtual bool visit(ReturnStatementAST *) { return true; }
@@ -319,7 +318,6 @@ public:
     virtual void endVisit(PointerAST *) { }
     virtual void endVisit(PointerToMemberAST *) { }
     virtual void endVisit(PostIncrDecrAST *) { }
-    virtual void endVisit(PostfixExpressionAST *) { }
     virtual void endVisit(QualifiedNameAST *) { }
     virtual void endVisit(ReferenceAST *) { }
     virtual void endVisit(ReturnStatementAST *) { }
diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h
index dbec328c2a7..897edb6ccc6 100644
--- a/src/shared/cplusplus/ASTfwd.h
+++ b/src/shared/cplusplus/ASTfwd.h
@@ -165,7 +165,6 @@ class PointerToMemberAST;
 class PostIncrDecrAST;
 class PostfixAST;
 class PostfixDeclaratorAST;
-class PostfixExpressionAST;
 class PtrOperatorAST;
 class QtEnumDeclarationAST;
 class QtFlagsDeclarationAST;
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index 17ac2ebfe99..6a24d3a51dd 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -248,15 +248,6 @@ bool CheckExpression::visit(TypeConstructorCallAST *ast)
     return false;
 }
 
-bool CheckExpression::visit(PostfixExpressionAST *ast)
-{
-    FullySpecifiedType exprTy = semantic()->check(ast->base_expression, _scope);
-    for (PostfixListAST *it = ast->postfix_expression_list; it; it = it->next) {
-        accept(it->value); // ### not exactly.
-    }
-    return false;
-}
-
 bool CheckExpression::visit(SizeofExpressionAST *ast)
 {
     FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
@@ -348,6 +339,7 @@ bool CheckExpression::visit(CompoundLiteralAST *ast)
 
 bool CheckExpression::visit(CallAST *ast)
 {
+    FullySpecifiedType baseTy = semantic()->check(ast->base_expression, _scope);
     for (ExpressionListAST *it = ast->expression_list; it; it = it->next) {
         FullySpecifiedType exprTy = semantic()->check(it->value, _scope);
     }
@@ -356,18 +348,22 @@ bool CheckExpression::visit(CallAST *ast)
 
 bool CheckExpression::visit(ArrayAccessAST *ast)
 {
+    FullySpecifiedType baseTy = semantic()->check(ast->base_expression, _scope);
     FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
     return false;
 }
 
-bool CheckExpression::visit(PostIncrDecrAST *)
+bool CheckExpression::visit(PostIncrDecrAST *ast)
 {
+    FullySpecifiedType baseTy = semantic()->check(ast->base_expression, _scope);
     return false;
 }
 
 bool CheckExpression::visit(MemberAccessAST *ast)
 {
-    (void) semantic()->check(ast->member_name, _scope);
+    FullySpecifiedType baseTy = semantic()->check(ast->base_expression, _scope);
+    const Name *memberName = semantic()->check(ast->member_name, _scope);
+    (void) memberName;
     return false;
 }
 
diff --git a/src/shared/cplusplus/CheckExpression.h b/src/shared/cplusplus/CheckExpression.h
index 6c5452de11d..ce51541af38 100644
--- a/src/shared/cplusplus/CheckExpression.h
+++ b/src/shared/cplusplus/CheckExpression.h
@@ -82,7 +82,6 @@ protected:
     virtual bool visit(TypeidExpressionAST *ast);
     virtual bool visit(TypenameCallExpressionAST *ast);
     virtual bool visit(TypeConstructorCallAST *ast);
-    virtual bool visit(PostfixExpressionAST *ast);
     virtual bool visit(SizeofExpressionAST *ast);
     virtual bool visit(NumericLiteralAST *ast);
     virtual bool visit(BoolLiteralAST *ast);
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 13bc9ab63fb..47128a4d065 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -4325,28 +4325,26 @@ bool Parser::parsePostfixExpression(ExpressionAST *&node)
 {
     DEBUG_THIS_RULE();
     if (parseCorePostfixExpression(node)) {
-        PostfixListAST *postfix_expressions = 0,
-            **postfix_ptr = &postfix_expressions;
         while (LA()) {
             if (LA() == T_LPAREN) {
                 CallAST *ast = new (_pool) CallAST;
                 ast->lparen_token = consumeToken();
                 parseExpressionList(ast->expression_list);
                 match(T_RPAREN, &ast->rparen_token);
-                *postfix_ptr = new (_pool) PostfixListAST(ast);
-                postfix_ptr = &(*postfix_ptr)->next;
+                ast->base_expression = node;
+                node = ast;
             } else if (LA() == T_LBRACKET) {
                 ArrayAccessAST *ast = new (_pool) ArrayAccessAST;
                 ast->lbracket_token = consumeToken();
                 parseExpression(ast->expression);
                 match(T_RBRACKET, &ast->rbracket_token);
-                *postfix_ptr = new (_pool) PostfixListAST(ast);
-                postfix_ptr = &(*postfix_ptr)->next;
+                ast->base_expression = node;
+                node = ast;
             } else if (LA() == T_PLUS_PLUS || LA() == T_MINUS_MINUS) {
                 PostIncrDecrAST *ast = new (_pool) PostIncrDecrAST;
                 ast->incr_decr_token = consumeToken();
-                *postfix_ptr = new (_pool) PostfixListAST(ast);
-                postfix_ptr = &(*postfix_ptr)->next;
+                ast->base_expression = node;
+                node = ast;
             } else if (LA() == T_DOT || LA() == T_ARROW) {
                 MemberAccessAST *ast = new (_pool) MemberAccessAST;
                 ast->access_token = consumeToken();
@@ -4355,17 +4353,11 @@ bool Parser::parsePostfixExpression(ExpressionAST *&node)
                 if (! parseNameId(ast->member_name))
                     _translationUnit->error(cursor(), "expected unqualified-id before token `%s'",
                                             tok().spell());
-                *postfix_ptr = new (_pool) PostfixListAST(ast);
-                postfix_ptr = &(*postfix_ptr)->next;
+                ast->base_expression = node;
+                node = ast;
             } else break;
         } // while
 
-        if (postfix_expressions) {
-            PostfixExpressionAST *ast = new (_pool) PostfixExpressionAST;
-            ast->base_expression = node;
-            ast->postfix_expression_list = postfix_expressions;
-            node = ast;
-        }
         return true;
     }
     return false;
-- 
GitLab