From 392c80c6e4b3e0112d4fca50ee3351a6345db3fa Mon Sep 17 00:00:00 2001
From: Christian Kamm <kamm@incasoftware.de>
Date: Tue, 18 Sep 2012 12:57:51 +0200
Subject: [PATCH] C++11: Fix use of >> in template arguments.

Change-Id: Ic99ca897e7a3b9c82cf8c5093a90bf9c88dbb0ed
Reviewed-by: hjk <qthjk@ovi.com>
---
 src/libs/3rdparty/cplusplus/Parser.cpp        | 23 +++++++++------
 src/libs/3rdparty/cplusplus/Parser.h          |  3 +-
 .../3rdparty/cplusplus/TranslationUnit.cpp    | 28 +++++++++++++++++++
 src/libs/3rdparty/cplusplus/TranslationUnit.h |  2 ++
 .../cxx11/data/templateGreaterGreater.1.cpp   | 10 +++++++
 tests/auto/cplusplus/cxx11/tst_cxx11.cpp      |  1 +
 6 files changed, 57 insertions(+), 10 deletions(-)
 create mode 100644 tests/auto/cplusplus/cxx11/data/templateGreaterGreater.1.cpp

diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 64723254700..591d227b47d 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -107,7 +107,7 @@ inline int precedence(int tokenKind, bool templateArguments)
 {
     // ### this will/might need some tuning for C++0x
     // (see: [temp.names]p3)
-    if (templateArguments && tokenKind == T_GREATER)
+    if (templateArguments && (tokenKind == T_GREATER || tokenKind == T_GREATER_GREATER))
         return -1;
 
     if (lookAtAssignmentOperator(tokenKind))
@@ -212,6 +212,11 @@ bool Parser::switchTemplateArguments(bool templateArguments)
     return previousTemplateArguments;
 }
 
+bool Parser::maybeSplitGreaterGreaterToken(int n)
+{
+    return _translationUnit->maybeSplitGreaterGreaterToken(_tokenIndex + n - 1);
+}
+
 bool Parser::blockErrors(bool block)
 { return _translationUnit->blockErrors(block); }
 
@@ -433,9 +438,9 @@ bool Parser::parseTemplateId(NameAST *&node, unsigned template_token)
         ast->template_token = template_token;
         ast->identifier_token = consumeToken();
         ast->less_token = consumeToken();
-        if (LA() == T_GREATER || parseTemplateArgumentList(
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateArgumentList(
                 ast->template_argument_list)) {
-            if (LA() == T_GREATER) {
+            if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER) {
                 ast->greater_token = consumeToken();
                 node = ast;
                 return true;
@@ -1103,7 +1108,7 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
 
     if (LA() == T_LESS) {
         ast->less_token = consumeToken();
-        if (LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
             match(T_GREATER, &ast->greater_token);
     }
 
@@ -1318,7 +1323,7 @@ bool Parser::parseTemplateArgument(ExpressionAST *&node)
         if (_cxx0xEnabled && LA() == T_DOT_DOT_DOT)
             index = 2;
 
-        if (LA(index) == T_COMMA || LA(index) == T_GREATER)
+        if (LA(index) == T_COMMA || maybeSplitGreaterGreaterToken(index) || LA(index) == T_GREATER)
             return true;
     }
 
@@ -1796,7 +1801,7 @@ bool Parser::parseTemplateTypeParameter(DeclarationAST *&node)
         if (LA() == T_LESS)
             ast->less_token = consumeToken();
         parseTemplateParameterList(ast->template_parameter_list);
-        if (LA() == T_GREATER)
+        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER)
             ast->greater_token = consumeToken();
         if (LA() == T_CLASS)
             ast->class_token = consumeToken();
@@ -1816,7 +1821,7 @@ bool Parser::parseTemplateTypeParameter(DeclarationAST *&node)
     return false;
 }
 
-bool Parser::lookAtTypeParameter() const
+bool Parser::lookAtTypeParameter()
 {
     if (LA() == T_CLASS || LA() == T_TYPENAME) {
         if (LA(2) == T_IDENTIFIER) {
@@ -1827,7 +1832,7 @@ bool Parser::lookAtTypeParameter() const
                 return true;
 
             default:
-                return false;
+                return maybeSplitGreaterGreaterToken(3);
             }
         } else if (LA(2) == T_COLON_COLON) {
             // found something like template <typename ::foo::bar>...
@@ -2947,7 +2952,7 @@ bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId)
         if (acceptTemplateId && LA(2) == T_LESS) {
             bool blocked = blockErrors(true);
             if (parseTemplateId(node)
-                    && (! _templateArguments || (LA() == T_COMMA  || LA() == T_GREATER ||
+                    && (! _templateArguments || (LA() == T_COMMA  || maybeSplitGreaterGreaterToken() || LA() == T_GREATER ||
                                                  LA() == T_LPAREN || LA() == T_RPAREN  ||
                                                  LA() == T_STAR || LA() == T_AMPER || // ptr-operators
                                                  LA() == T_COLON_COLON))) {
diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h
index cb0c7803c53..472ad412a2e 100644
--- a/src/libs/3rdparty/cplusplus/Parser.h
+++ b/src/libs/3rdparty/cplusplus/Parser.h
@@ -259,7 +259,7 @@ public:
     bool skip(int l, int r);
     int find(int token, int stopAt);
 
-    bool lookAtTypeParameter() const;
+    bool lookAtTypeParameter();
     bool lookAtCVQualifier() const;
     bool lookAtFunctionSpecifier() const;
     bool lookAtStorageClassSpecifier() const;
@@ -277,6 +277,7 @@ public:
     int peekAtQtContextKeyword() const;
 
     bool switchTemplateArguments(bool templateArguments);
+    bool maybeSplitGreaterGreaterToken(int n = 1);
 
     bool blockErrors(bool block);
     void warning(unsigned index, const char *format, ...);
diff --git a/src/libs/3rdparty/cplusplus/TranslationUnit.cpp b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
index a26a23eabce..7afef149ef1 100644
--- a/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
+++ b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
@@ -552,6 +552,34 @@ unsigned TranslationUnit::findPreviousLineOffset(unsigned tokenIndex) const
     return lineOffset;
 }
 
+bool TranslationUnit::maybeSplitGreaterGreaterToken(unsigned tokenIndex)
+{
+    Token &tok = _tokens->at(tokenIndex);
+    if (tok.kind() != T_GREATER_GREATER)
+        return false;
+
+    tok.f.kind = T_GREATER;
+    tok.f.length = 1;
+
+    Token newGreater;
+    newGreater.f.kind = T_GREATER;
+    newGreater.f.expanded = tok.f.expanded;
+    newGreater.f.generated = tok.f.generated;
+    newGreater.f.length = 1;
+    newGreater.offset = tok.offset + 1;
+
+    _tokens->insert(_tokens->begin() + tokenIndex + 1, newGreater);
+
+    std::map<unsigned, std::pair<unsigned, unsigned> >::const_iterator it =
+            _expandedLineColumn.find(tok.offset);
+    if (it != _expandedLineColumn.end()) {
+        const std::pair<unsigned, unsigned> newPosition(it->second.first, it->second.second + 1);
+        _expandedLineColumn.insert(std::make_pair(newGreater.offset, newPosition));
+    }
+
+    return true;
+}
+
 void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out)
 {
     unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)];
diff --git a/src/libs/3rdparty/cplusplus/TranslationUnit.h b/src/libs/3rdparty/cplusplus/TranslationUnit.h
index 95832f43281..f6ac1959dbf 100644
--- a/src/libs/3rdparty/cplusplus/TranslationUnit.h
+++ b/src/libs/3rdparty/cplusplus/TranslationUnit.h
@@ -134,6 +134,8 @@ public:
 
     unsigned findPreviousLineOffset(unsigned tokenIndex) const;
 
+    bool maybeSplitGreaterGreaterToken(unsigned tokenIndex);
+
 public:
     struct PPLine {
         unsigned offset;
diff --git a/tests/auto/cplusplus/cxx11/data/templateGreaterGreater.1.cpp b/tests/auto/cplusplus/cxx11/data/templateGreaterGreater.1.cpp
new file mode 100644
index 00000000000..c07d0a0e4fb
--- /dev/null
+++ b/tests/auto/cplusplus/cxx11/data/templateGreaterGreater.1.cpp
@@ -0,0 +1,10 @@
+template <class i, int j = 1>
+class Y {};
+template <int i>
+class X {};
+
+Y<X<6>, 7> x;
+Y<X<1>> y;
+X< (1 >> 2) > z;
+auto a = static_cast<X<1>>(X<1>());
+
diff --git a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
index 8ccc5567586..3566c11a3e1 100644
--- a/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
+++ b/tests/auto/cplusplus/cxx11/tst_cxx11.cpp
@@ -144,6 +144,7 @@ void tst_cxx11::parse_data()
     QTest::newRow("rangeFor.1") << "rangeFor.1.cpp" << "";
     QTest::newRow("aliasDecl.1") << "aliasDecl.1.cpp" << "";
     QTest::newRow("enums.1") << "enums.1.cpp" << "";
+    QTest::newRow("templateGreaterGreater.1") << "templateGreaterGreater.1.cpp" << "";
 }
 
 void tst_cxx11::parse()
-- 
GitLab