From ecd54059d3a0a18fd5e18c48b2c69761324d22c5 Mon Sep 17 00:00:00 2001
From: Christian Kamm <christian.d.kamm@nokia.com>
Date: Mon, 17 Sep 2012 13:47:18 +0200
Subject: [PATCH] C++11: Add alignof() expression.

Change-Id: Id3fb30b9a16ea724bab0d5b05e8cbddb0064e6eb
Reviewed-by: hjk <qthjk@ovi.com>
---
 src/libs/3rdparty/cplusplus/AST.cpp           | 30 +++++++++++++++++++
 src/libs/3rdparty/cplusplus/AST.h             | 29 ++++++++++++++++++
 src/libs/3rdparty/cplusplus/ASTClone.cpp      | 11 +++++++
 src/libs/3rdparty/cplusplus/ASTMatch0.cpp     |  8 +++++
 src/libs/3rdparty/cplusplus/ASTMatcher.cpp    | 19 ++++++++++++
 src/libs/3rdparty/cplusplus/ASTMatcher.h      |  1 +
 .../3rdparty/cplusplus/ASTPatternBuilder.h    |  7 +++++
 src/libs/3rdparty/cplusplus/ASTVisit.cpp      |  8 +++++
 src/libs/3rdparty/cplusplus/ASTVisitor.h      |  2 ++
 src/libs/3rdparty/cplusplus/ASTfwd.h          |  1 +
 src/libs/3rdparty/cplusplus/Parser.cpp        | 18 +++++++++++
 .../cplusplus/cxx11/data/alignofAlignas.1.cpp |  2 ++
 tests/auto/cplusplus/cxx11/tst_cxx11.cpp      |  1 +
 tests/tools/cplusplus-dump/dumpers.inc        | 12 ++++++++
 14 files changed, 149 insertions(+)
 create mode 100644 tests/auto/cplusplus/cxx11/data/alignofAlignas.1.cpp

diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp
index 05c4782f975..c3e6e7c6a43 100644
--- a/src/libs/3rdparty/cplusplus/AST.cpp
+++ b/src/libs/3rdparty/cplusplus/AST.cpp
@@ -4407,3 +4407,33 @@ unsigned RangeBasedForStatementAST::lastToken() const
     return 1;
 }
 
+/** \generated */
+unsigned AlignofExpressionAST::firstToken() const
+{
+    if (alignof_token)
+        return alignof_token;
+    if (lparen_token)
+        return lparen_token;
+    if (typeId)
+        if (unsigned candidate = typeId->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    return 0;
+}
+
+/** \generated */
+unsigned AlignofExpressionAST::lastToken() const
+{
+    if (rparen_token)
+        return rparen_token + 1;
+    if (typeId)
+        if (unsigned candidate = typeId->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (alignof_token)
+        return alignof_token + 1;
+    return 1;
+}
+
diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h
index 2c7edf14499..2f1aabf72ba 100644
--- a/src/libs/3rdparty/cplusplus/AST.h
+++ b/src/libs/3rdparty/cplusplus/AST.h
@@ -125,6 +125,7 @@ public:
     virtual AST *clone(MemoryPool *pool) const = 0;
 
     virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
+    virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
     virtual ArrayAccessAST *asArrayAccess() { return 0; }
     virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
     virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
@@ -3026,6 +3027,34 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
+class CPLUSPLUS_EXPORT AlignofExpressionAST: public ExpressionAST
+{
+public:
+    unsigned alignof_token;
+    unsigned lparen_token;
+    TypeIdAST *typeId;
+    unsigned rparen_token;
+
+public:
+    AlignofExpressionAST()
+        : alignof_token(0)
+        , lparen_token(0)
+        , typeId(0)
+        , rparen_token(0)
+    {}
+
+    virtual AlignofExpressionAST *asAlignofExpression() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual AlignofExpressionAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
 class CPLUSPLUS_EXPORT PointerLiteralAST: public ExpressionAST
 {
 public:
diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp
index 2a3f95bed0e..8fc94476275 100644
--- a/src/libs/3rdparty/cplusplus/ASTClone.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp
@@ -1137,6 +1137,17 @@ SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+AlignofExpressionAST *AlignofExpressionAST::clone(MemoryPool *pool) const
+{
+    AlignofExpressionAST *ast = new (pool) AlignofExpressionAST;
+    ast->alignof_token = alignof_token;
+    ast->lparen_token = lparen_token;
+    if (typeId)
+        ast->typeId = typeId->clone(pool);
+    ast->rparen_token = rparen_token;
+    return ast;
+}
+
 PointerLiteralAST *PointerLiteralAST::clone(MemoryPool *pool) const
 {
     PointerLiteralAST *ast = new (pool) PointerLiteralAST;
diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
index 26acc7290a2..e51604fe45a 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
@@ -776,6 +776,14 @@ bool SizeofExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
     return false;
 }
 
+bool AlignofExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (AlignofExpressionAST *_other = pattern->asAlignofExpression())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
 bool PointerLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
 {
     if (PointerLiteralAST *_other = pattern->asPointerLiteral())
diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
index b168a38fb43..71e030ac3c8 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
@@ -1925,6 +1925,25 @@ bool ASTMatcher::match(SizeofExpressionAST *node, SizeofExpressionAST *pattern)
     return true;
 }
 
+bool ASTMatcher::match(AlignofExpressionAST *node, AlignofExpressionAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->alignof_token = node->alignof_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->typeId)
+        pattern->typeId = node->typeId;
+    else if (! AST::match(node->typeId, pattern->typeId, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    return true;
+}
+
 bool ASTMatcher::match(PointerLiteralAST *node, PointerLiteralAST *pattern)
 {
     (void) node;
diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h
index 4ab940cd585..add9bddd4d6 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatcher.h
+++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h
@@ -32,6 +32,7 @@ public:
     virtual ~ASTMatcher();
 
     virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
+    virtual bool match(AlignofExpressionAST *node, AlignofExpressionAST *pattern);
     virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern);
     virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
     virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
index 90ec0586d26..10116ac6bcf 100644
--- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
+++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
@@ -747,6 +747,13 @@ public:
         return __ast;
     }
 
+    AlignofExpressionAST *AlignofExpression(TypeIdAST *typeId = 0)
+    {
+        AlignofExpressionAST *__ast = new (&pool) AlignofExpressionAST;
+        __ast->typeId = typeId;
+        return __ast;
+    }
+
     PointerLiteralAST *PointerLiteral()
     {
         PointerLiteralAST *__ast = new (&pool) PointerLiteralAST;
diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp
index cec357b4add..7fe3e6eca5a 100644
--- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp
@@ -828,6 +828,14 @@ void SizeofExpressionAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void AlignofExpressionAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(typeId, visitor);
+    }
+    visitor->endVisit(this);
+}
+
 void PointerLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h
index 14040b6defc..e6734ecf737 100644
--- a/src/libs/3rdparty/cplusplus/ASTVisitor.h
+++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h
@@ -74,6 +74,7 @@ public:
     virtual void postVisit(AST *) {}
 
     virtual bool visit(AccessDeclarationAST *) { return true; }
+    virtual bool visit(AlignofExpressionAST *) { return true; }
     virtual bool visit(ArrayAccessAST *) { return true; }
     virtual bool visit(ArrayDeclaratorAST *) { return true; }
     virtual bool visit(ArrayInitializerAST *) { return true; }
@@ -218,6 +219,7 @@ public:
     virtual bool visit(WhileStatementAST *) { return true; }
 
     virtual void endVisit(AccessDeclarationAST *) {}
+    virtual void endVisit(AlignofExpressionAST *) {}
     virtual void endVisit(ArrayAccessAST *) {}
     virtual void endVisit(ArrayDeclaratorAST *) {}
     virtual void endVisit(ArrayInitializerAST *) {}
diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h
index 6847f595e93..4d07f6507d9 100644
--- a/src/libs/3rdparty/cplusplus/ASTfwd.h
+++ b/src/libs/3rdparty/cplusplus/ASTfwd.h
@@ -32,6 +32,7 @@ class ASTVisitor;
 class ASTMatcher;
 
 class AccessDeclarationAST;
+class AlignofExpressionAST;
 class ArrayAccessAST;
 class ArrayDeclaratorAST;
 class ArrayInitializerAST;
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 16b5ba18e94..04246b9cf06 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -4860,6 +4860,24 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node)
         return true;
     }
 
+    case T_ALIGNOF: {
+        if (!_cxx0xEnabled)
+            break;
+
+        AlignofExpressionAST *ast = new (_pool) AlignofExpressionAST;
+        ast->alignof_token = consumeToken();
+
+        match(T_LPAREN, &ast->lparen_token);
+        ExpressionAST *temp = 0;
+        parseTypeId(temp);
+        if (temp)
+            ast->typeId = temp->asTypeId();
+        match(T_RPAREN, &ast->rparen_token);
+
+        node = ast;
+        return true;
+    }
+
     default:
         break;
     } // switch
diff --git a/tests/auto/cplusplus/cxx11/data/alignofAlignas.1.cpp b/tests/auto/cplusplus/cxx11/data/alignofAlignas.1.cpp
new file mode 100644
index 00000000000..5ba43661ed6
--- /dev/null
+++ b/tests/auto/cplusplus/cxx11/data/alignofAlignas.1.cpp
@@ -0,0 +1,2 @@
+int i = alignof(int);
+int t = alignof(C::foo) * 7 + alignof(Foo *);
diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
index d1c5889b759..684de7ae306 100644
--- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
+++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
@@ -140,6 +140,7 @@ void tst_cxx11::parse_data()
     QTest::newRow("braceInitializers.2") << "braceInitializers.2.cpp" << "";
     QTest::newRow("defaultdeleteInitializer.1") << "defaultdeleteInitializer.1.cpp" << "";
     QTest::newRow("refQualifier.1") << "refQualifier.1.cpp" << "";
+    QTest::newRow("alignofAlignas.1") << "alignofAlignas.1.cpp" << "";
 }
 
 void tst_cxx11::parse()
diff --git a/tests/tools/cplusplus-dump/dumpers.inc b/tests/tools/cplusplus-dump/dumpers.inc
index 3bddba82479..52717595151 100644
--- a/tests/tools/cplusplus-dump/dumpers.inc
+++ b/tests/tools/cplusplus-dump/dumpers.inc
@@ -1104,6 +1104,18 @@ virtual bool visit(SizeofExpressionAST *ast)
     return false;
 }
 
+virtual bool visit(AlignofExpressionAST *ast)
+{
+    if (ast->alignof_token)
+        terminal(ast->alignof_token, ast);
+    if (ast->lparen_token)
+        terminal(ast->lparen_token, ast);
+    nonterminal(ast->typeId);
+    if (ast->rparen_token)
+        terminal(ast->rparen_token, ast);
+    return false;
+}
+
 virtual bool visit(PointerLiteralAST *ast)
 {
     if (ast->literal_token)
-- 
GitLab