From 1d3dc3015343a9ec55d58115390f5dcf9ba92297 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Thu, 2 Feb 2012 13:39:24 +0100
Subject: [PATCH] C++11: add support for static_assert.

Change-Id: I82d8d60acaa9265fd25e0a3734855b19bdef9c06
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
---
 src/libs/3rdparty/cplusplus/AST.cpp           | 44 +++++++++++++++++++
 src/libs/3rdparty/cplusplus/AST.h             | 35 +++++++++++++++
 src/libs/3rdparty/cplusplus/ASTClone.cpp      | 15 +++++++
 src/libs/3rdparty/cplusplus/ASTMatch0.cpp     |  8 ++++
 src/libs/3rdparty/cplusplus/ASTMatcher.cpp    | 28 ++++++++++++
 src/libs/3rdparty/cplusplus/ASTMatcher.h      |  1 +
 .../3rdparty/cplusplus/ASTPatternBuilder.h    |  8 ++++
 src/libs/3rdparty/cplusplus/ASTVisit.cpp      |  9 ++++
 src/libs/3rdparty/cplusplus/ASTVisitor.h      |  2 +
 src/libs/3rdparty/cplusplus/ASTfwd.h          |  1 +
 src/libs/3rdparty/cplusplus/Keywords.cpp      | 28 +++++++++++-
 src/libs/3rdparty/cplusplus/Parser.cpp        | 26 +++++++++++
 src/libs/3rdparty/cplusplus/Parser.h          |  1 +
 src/libs/3rdparty/cplusplus/Token.cpp         |  2 +-
 src/libs/3rdparty/cplusplus/Token.h           |  1 +
 src/libs/cplusplus/FindUsages.cpp             |  6 +++
 src/libs/cplusplus/FindUsages.h               |  1 +
 tests/manual/plain-cplusplus/main.cpp         |  1 +
 18 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp
index 139a856106d..109cc63455a 100644
--- a/src/libs/3rdparty/cplusplus/AST.cpp
+++ b/src/libs/3rdparty/cplusplus/AST.cpp
@@ -4269,3 +4269,47 @@ unsigned NoExceptSpecificationAST::lastToken() const
     return 1;
 }
 
+/** \generated */
+unsigned StaticAssertDeclarationAST::firstToken() const
+{
+    if (static_assert_token)
+        return static_assert_token;
+    if (lparen_token)
+        return lparen_token;
+    if (expression)
+        if (unsigned candidate = expression->firstToken())
+            return candidate;
+    if (comma_token)
+        return comma_token;
+    if (string_literal)
+        if (unsigned candidate = string_literal->firstToken())
+            return candidate;
+    if (rparen_token)
+        return rparen_token;
+    if (semicolon_token)
+        return semicolon_token;
+    return 0;
+}
+
+/** \generated */
+unsigned StaticAssertDeclarationAST::lastToken() const
+{
+    if (semicolon_token)
+        return semicolon_token + 1;
+    if (rparen_token)
+        return rparen_token + 1;
+    if (string_literal)
+        if (unsigned candidate = string_literal->lastToken())
+            return candidate;
+    if (comma_token)
+        return comma_token + 1;
+    if (expression)
+        if (unsigned candidate = expression->lastToken())
+            return candidate;
+    if (lparen_token)
+        return lparen_token + 1;
+    if (static_assert_token)
+        return static_assert_token + 1;
+    return 1;
+}
+
diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h
index b02f771ab43..c6939876e6c 100644
--- a/src/libs/3rdparty/cplusplus/AST.h
+++ b/src/libs/3rdparty/cplusplus/AST.h
@@ -254,6 +254,7 @@ public:
     virtual SizeofExpressionAST *asSizeofExpression() { return 0; }
     virtual SpecifierAST *asSpecifier() { return 0; }
     virtual StatementAST *asStatement() { return 0; }
+    virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return 0; }
     virtual StringLiteralAST *asStringLiteral() { return 0; }
     virtual SwitchStatementAST *asSwitchStatement() { return 0; }
     virtual TemplateDeclarationAST *asTemplateDeclaration() { return 0; }
@@ -3062,6 +3063,40 @@ protected:
     virtual bool match0(AST *, ASTMatcher *);
 };
 
+class CPLUSPLUS_EXPORT StaticAssertDeclarationAST: public DeclarationAST
+{
+public:
+    unsigned static_assert_token;
+    unsigned lparen_token;
+    ExpressionAST *expression;
+    unsigned comma_token;
+    ExpressionAST *string_literal;
+    unsigned rparen_token;
+    unsigned semicolon_token;
+
+public:
+    StaticAssertDeclarationAST()
+        : static_assert_token(0)
+        , lparen_token(0)
+        , expression(0)
+        , comma_token(0)
+        , string_literal(0)
+        , rparen_token(0)
+        , semicolon_token(0)
+    {}
+
+    virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return this; }
+
+    virtual unsigned firstToken() const;
+    virtual unsigned lastToken() const;
+
+    virtual StaticAssertDeclarationAST *clone(MemoryPool *pool) const;
+
+protected:
+    virtual void accept0(ASTVisitor *visitor);
+    virtual bool match0(AST *, ASTMatcher *);
+};
+
 class CPLUSPLUS_EXPORT StringLiteralAST: public ExpressionAST
 {
 public:
diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp
index 6cca878c193..e65be49c38e 100644
--- a/src/libs/3rdparty/cplusplus/ASTClone.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp
@@ -1142,6 +1142,21 @@ NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const
     return ast;
 }
 
+StaticAssertDeclarationAST *StaticAssertDeclarationAST::clone(MemoryPool *pool) const
+{
+    StaticAssertDeclarationAST *ast = new (pool) StaticAssertDeclarationAST;
+    ast->static_assert_token = static_assert_token;
+    ast->lparen_token = lparen_token;
+    if (expression)
+        ast->expression = expression->clone(pool);
+    ast->comma_token = comma_token;
+    if (string_literal)
+        ast->string_literal = string_literal->clone(pool);
+    ast->rparen_token = rparen_token;
+    ast->semicolon_token = semicolon_token;
+    return ast;
+}
+
 StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const
 {
     StringLiteralAST *ast = new (pool) StringLiteralAST;
diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
index 9694be4b4d5..127993ea2a6 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp
@@ -800,6 +800,14 @@ bool NestedExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
     return false;
 }
 
+bool StaticAssertDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
+{
+    if (StaticAssertDeclarationAST *_other = pattern->asStaticAssertDeclaration())
+        return matcher->match(this, _other);
+
+    return false;
+}
+
 bool StringLiteralAST::match0(AST *pattern, ASTMatcher *matcher)
 {
     if (StringLiteralAST *_other = pattern->asStringLiteral())
diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
index 0f7d7056e02..daafb070b19 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp
@@ -1917,6 +1917,34 @@ bool ASTMatcher::match(NestedExpressionAST *node, NestedExpressionAST *pattern)
     return true;
 }
 
+bool ASTMatcher::match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *pattern)
+{
+    (void) node;
+    (void) pattern;
+
+    pattern->static_assert_token = node->static_assert_token;
+
+    pattern->lparen_token = node->lparen_token;
+
+    if (! pattern->expression)
+        pattern->expression = node->expression;
+    else if (! AST::match(node->expression, pattern->expression, this))
+        return false;
+
+    pattern->comma_token = node->comma_token;
+
+    if (! pattern->string_literal)
+        pattern->string_literal = node->string_literal;
+    else if (! AST::match(node->string_literal, pattern->string_literal, this))
+        return false;
+
+    pattern->rparen_token = node->rparen_token;
+
+    pattern->semicolon_token = node->semicolon_token;
+
+    return true;
+}
+
 bool ASTMatcher::match(StringLiteralAST *node, StringLiteralAST *pattern)
 {
     (void) node;
diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h
index 84ec77c84d4..4c8612ccdc6 100644
--- a/src/libs/3rdparty/cplusplus/ASTMatcher.h
+++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h
@@ -151,6 +151,7 @@ public:
     virtual bool match(SimpleNameAST *node, SimpleNameAST *pattern);
     virtual bool match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern);
     virtual bool match(SizeofExpressionAST *node, SizeofExpressionAST *pattern);
+    virtual bool match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *pattern);
     virtual bool match(StringLiteralAST *node, StringLiteralAST *pattern);
     virtual bool match(SwitchStatementAST *node, SwitchStatementAST *pattern);
     virtual bool match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern);
diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
index f9ab027c79b..cbc2ccdaf8d 100644
--- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
+++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
@@ -759,6 +759,14 @@ public:
         return __ast;
     }
 
+    StaticAssertDeclarationAST *StaticAssertDeclaration(ExpressionAST *expression = 0, ExpressionAST *string_literal = 0)
+    {
+        StaticAssertDeclarationAST *__ast = new (&pool) StaticAssertDeclarationAST;
+        __ast->expression = expression;
+        __ast->string_literal = string_literal;
+        return __ast;
+    }
+
     StringLiteralAST *StringLiteral(StringLiteralAST *next = 0)
     {
         StringLiteralAST *__ast = new (&pool) StringLiteralAST;
diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp
index af0ef827ca3..2e99c3155a1 100644
--- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp
+++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp
@@ -843,6 +843,15 @@ void NestedExpressionAST::accept0(ASTVisitor *visitor)
     visitor->endVisit(this);
 }
 
+void StaticAssertDeclarationAST::accept0(ASTVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        accept(expression, visitor);
+        accept(string_literal, visitor);
+    }
+    visitor->endVisit(this);
+}
+
 void StringLiteralAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h
index 16f7ebbe682..9ca6cf57f6d 100644
--- a/src/libs/3rdparty/cplusplus/ASTVisitor.h
+++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h
@@ -193,6 +193,7 @@ public:
     virtual bool visit(SimpleNameAST *) { return true; }
     virtual bool visit(SimpleSpecifierAST *) { return true; }
     virtual bool visit(SizeofExpressionAST *) { return true; }
+    virtual bool visit(StaticAssertDeclarationAST *) { return true; }
     virtual bool visit(StringLiteralAST *) { return true; }
     virtual bool visit(SwitchStatementAST *) { return true; }
     virtual bool visit(TemplateDeclarationAST *) { return true; }
@@ -334,6 +335,7 @@ public:
     virtual void endVisit(SimpleNameAST *) {}
     virtual void endVisit(SimpleSpecifierAST *) {}
     virtual void endVisit(SizeofExpressionAST *) {}
+    virtual void endVisit(StaticAssertDeclarationAST *) {}
     virtual void endVisit(StringLiteralAST *) {}
     virtual void endVisit(SwitchStatementAST *) {}
     virtual void endVisit(TemplateDeclarationAST *) {}
diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h
index 7df129cbd82..9858a42ab21 100644
--- a/src/libs/3rdparty/cplusplus/ASTfwd.h
+++ b/src/libs/3rdparty/cplusplus/ASTfwd.h
@@ -161,6 +161,7 @@ class SimpleSpecifierAST;
 class SizeofExpressionAST;
 class SpecifierAST;
 class StatementAST;
+class StaticAssertDeclarationAST;
 class StringLiteralAST;
 class SwitchStatementAST;
 class TemplateDeclarationAST;
diff --git a/src/libs/3rdparty/cplusplus/Keywords.cpp b/src/libs/3rdparty/cplusplus/Keywords.cpp
index a09e0f05205..49c7e442d0e 100644
--- a/src/libs/3rdparty/cplusplus/Keywords.cpp
+++ b/src/libs/3rdparty/cplusplus/Keywords.cpp
@@ -1360,7 +1360,7 @@ static inline int classify12(const char *s, bool q, bool) {
   return T_IDENTIFIER;
 }
 
-static inline int classify13(const char *s, bool, bool) {
+static inline int classify13(const char *s, bool, bool x) {
   if (s[0] == '_') {
     if (s[1] == '_') {
       if (s[2] == 'a') {
@@ -1387,6 +1387,32 @@ static inline int classify13(const char *s, bool, bool) {
         }
       }
     }
+  } else if (x && s[0] == 's') {
+    if (s[1] == 't') {
+      if (s[2] == 'a') {
+        if (s[3] == 't') {
+          if (s[4] == 'i') {
+            if (s[5] == 'c') {
+              if (s[6] == '_') {
+                if (s[7] == 'a') {
+                  if (s[8] == 's') {
+                    if (s[9] == 's') {
+                      if (s[10] == 'e') {
+                        if (s[11] == 'r') {
+                          if (s[12] == 't') {
+                            return T_STATIC_ASSERT;
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
   }
   return T_IDENTIFIER;
 }
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 1ad7996f40d..a8c8be79797 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -269,6 +269,8 @@ void Parser::skipUntilDeclaration()
         // declarations
         case T_ENUM:
         case T_NAMESPACE:
+        case T_INLINE:
+        case T_STATIC_ASSERT:
         case T_ASM:
         case T_EXPORT:
         case T_AT_CLASS:
@@ -621,6 +623,7 @@ bool Parser::parseDeclaration(DeclarationAST *&node)
         consumeToken();
         break;
 
+    // C++11
     case T_INLINE:
         if (_cxx0xEnabled && LA(2) == T_NAMESPACE)
             return parseNamespace(node);
@@ -707,6 +710,25 @@ bool Parser::parseLinkageBody(DeclarationAST *&node)
     return false;
 }
 
+bool Parser::parseStaticAssertDeclaration(DeclarationAST *&node)
+{
+    DEBUG_THIS_RULE();
+    if (LA() != T_STATIC_ASSERT)
+        return false;
+
+    StaticAssertDeclarationAST *ast = new (_pool) StaticAssertDeclarationAST;
+    ast->static_assert_token = consumeToken();
+    match(T_LPAREN, &ast->lparen_token);
+    parseConstantExpression(ast->expression);
+    match(T_COMMA, &ast->comma_token);
+    parseStringLiteral(ast->string_literal);
+    match(T_RPAREN, &ast->rparen_token);
+    match(T_SEMICOLON, &ast->semicolon_token);
+
+    node = ast;
+    return true;
+}
+
 // ### rename parseNamespaceAliarOrDeclaration?
 bool Parser::parseNamespace(DeclarationAST *&node)
 {
@@ -2259,6 +2281,10 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node, ClassSpecifierAST *
     case T_Q_INTERFACES:
         return parseQtInterfaces(node);
 
+    // C++11
+    case T_STATIC_ASSERT:
+        return parseStaticAssertDeclaration(node);
+
     default:
         return parseSimpleDeclaration(node, declaringClass);
     } // switch
diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h
index de2acfcb547..24a1b3f0128 100644
--- a/src/libs/3rdparty/cplusplus/Parser.h
+++ b/src/libs/3rdparty/cplusplus/Parser.h
@@ -125,6 +125,7 @@ public:
     bool parseName(NameAST *&node, bool acceptTemplateId = true);
     bool parseNestedNameSpecifier(NestedNameSpecifierListAST *&node, bool acceptTemplateId);
     bool parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool acceptTemplateId);
+    bool parseStaticAssertDeclaration(DeclarationAST *&node);
     bool parseNamespace(DeclarationAST *&node);
     bool parseNamespaceAliasDefinition(DeclarationAST *&node);
     bool parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node);
diff --git a/src/libs/3rdparty/cplusplus/Token.cpp b/src/libs/3rdparty/cplusplus/Token.cpp
index 4b40707cbfe..1ebb54070a7 100644
--- a/src/libs/3rdparty/cplusplus/Token.cpp
+++ b/src/libs/3rdparty/cplusplus/Token.cpp
@@ -48,7 +48,7 @@ static const char *token_names[] = {
     ("mutable"), ("namespace"), ("new"), ("noexcept"),
     ("nullptr"), ("operator"), ("private"),
     ("protected"), ("public"), ("register"), ("reinterpret_cast"),
-    ("return"), ("short"), ("signed"), ("sizeof"), ("static"),
+    ("return"), ("short"), ("signed"), ("sizeof"), ("static"),("static_assert"),
     ("static_cast"), ("struct"), ("switch"), ("template"), ("this"),
     ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"),
     ("union"), ("unsigned"), ("using"), ("virtual"), ("void"),
diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h
index bc98176b6ee..7a2d13264e7 100644
--- a/src/libs/3rdparty/cplusplus/Token.h
+++ b/src/libs/3rdparty/cplusplus/Token.h
@@ -148,6 +148,7 @@ enum Kind {
     T_SIGNED,
     T_SIZEOF,
     T_STATIC,
+    T_STATIC_ASSERT,
     T_STATIC_CAST,
     T_STRUCT,
     T_SWITCH,
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index 6e9c5257635..cbd3e8a27ea 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -1674,6 +1674,12 @@ bool FindUsages::visit(ParameterDeclarationAST *ast)
     return false;
 }
 
+bool FindUsages::visit(StaticAssertDeclarationAST *ast)
+{
+    this->expression(ast->expression);
+    return false;
+}
+
 bool FindUsages::visit(TemplateDeclarationAST *ast)
 {
     // unsigned export_token = ast->export_token;
diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h
index e4df7e82243..389c670ff56 100644
--- a/src/libs/cplusplus/FindUsages.h
+++ b/src/libs/cplusplus/FindUsages.h
@@ -236,6 +236,7 @@ protected:
     virtual bool visit(NamespaceAST *ast);
     virtual bool visit(NamespaceAliasDefinitionAST *ast);
     virtual bool visit(ParameterDeclarationAST *ast);
+    virtual bool visit(StaticAssertDeclarationAST *ast);
     virtual bool visit(TemplateDeclarationAST *ast);
     virtual bool visit(TypenameTypeParameterAST *ast);
     virtual bool visit(TemplateTypeParameterAST *ast);
diff --git a/tests/manual/plain-cplusplus/main.cpp b/tests/manual/plain-cplusplus/main.cpp
index dfd51ca5b9f..49d2f8bef70 100644
--- a/tests/manual/plain-cplusplus/main.cpp
+++ b/tests/manual/plain-cplusplus/main.cpp
@@ -145,6 +145,7 @@ void parse(const char *fileName, const char *source, unsigned size)
     Control control;
     TranslationUnit unit(&control, control.stringLiteral(fileName));
     unit.setSource(source, size);
+    unit.setCxxOxEnabled(true);
     unit.parse();
 
 #if 1
-- 
GitLab