diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 64723254700ad2d051ee60dbfc43e64405cb33b1..591d227b47da30f1118459126ec4fb9f8248d09f 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 cb0c7803c536a0580673b942716bb01a9fc2b6d3..472ad412a2e9fbb6f2f96fd550ebf0e33d268e88 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 a26a23eabce3b98b38dfe002fabe3e8c079bd762..7afef149ef13b28b31bae1b1de8f9d902498811c 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 95832f4328141d721cbbf3a96e769f9d29790fda..f6ac1959dbf50dae4152aeff62a0cb90c067ea23 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 0000000000000000000000000000000000000000..c07d0a0e4fbd69036b0e9cc5b08dc54201f47ea7 --- /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 8ccc55675869b99cfe224c2f8627798533480fa7..3566c11a3e149719f73ad92664eff3044c95f3f8 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()