From 2a966a89177612c42574c6700d878fe864df4d76 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Wed, 25 Feb 2015 21:22:16 +0100 Subject: [PATCH] C++: Support ellipsis on variadic inheritance parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I571aefdb1f2aba88ba0c7710f16b6d8ad2e8f5a8 Reviewed-by: André Hartmann Reviewed-by: Orgad Shaneh Reviewed-by: Nikolai Kosjar --- src/libs/3rdparty/cplusplus/AST.cpp | 4 +- src/libs/3rdparty/cplusplus/AST.h | 2 + src/libs/3rdparty/cplusplus/ASTClone.cpp | 1 + src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 2 + src/libs/3rdparty/cplusplus/Bind.cpp | 2 + src/libs/3rdparty/cplusplus/Parser.cpp | 5 ++ src/libs/3rdparty/cplusplus/Symbols.cpp | 6 +++ src/libs/3rdparty/cplusplus/Symbols.h | 4 ++ src/tools/cplusplus-ast2png/dumpers.inc | 2 + tests/auto/cplusplus/ast/tst_ast.cpp | 54 +++++++++++++++++++++- 10 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 0eb73f58fba..be235a8c41c 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -89,7 +89,9 @@ unsigned BaseSpecifierAST::firstToken() const unsigned BaseSpecifierAST::lastToken() const { - if (name) + if (ellipsis_token) + return ellipsis_token; + else if (name) return name->lastToken(); else if (virtual_token && access_specifier_token) return std::max(virtual_token, access_specifier_token) + 1; diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 144af639e46..b8cda42b59c 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -1002,6 +1002,7 @@ public: unsigned virtual_token; unsigned access_specifier_token; NameAST *name; + unsigned ellipsis_token; public: // annotations BaseClass *symbol; @@ -1011,6 +1012,7 @@ public: : virtual_token(0) , access_specifier_token(0) , name(0) + , ellipsis_token(0) , symbol(0) {} diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 3458846ea04..647929ad319 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -287,6 +287,7 @@ BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const ast->access_specifier_token = access_specifier_token; if (name) ast->name = name->clone(pool); + ast->ellipsis_token = ellipsis_token; return ast; } diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 055b55a32d8..ed8ef6b09f8 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -462,6 +462,8 @@ bool ASTMatcher::match(BaseSpecifierAST *node, BaseSpecifierAST *pattern) else if (! AST::match(node->name, pattern->name, this)) return false; + pattern->ellipsis_token = node->ellipsis_token; + return true; } diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index e3fd96de983..b80da2be4a0 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -429,6 +429,8 @@ void Bind::baseSpecifier(BaseSpecifierAST *ast, unsigned colon_token, Class *kla const int visibility = visibilityForAccessSpecifier(tokenKind(ast->access_specifier_token)); baseClass->setVisibility(visibility); // ### well, not exactly. } + if (ast->ellipsis_token) + baseClass->setVariadic(true); klass->addBaseClass(baseClass); ast->symbol = baseClass; } diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 7c330ce3300..8229aff5ed5 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -3006,6 +3006,11 @@ bool Parser::parseBaseSpecifier(BaseSpecifierListAST *&node) if (! ast->name) error(cursor(), "expected class-name"); + // a name can have ellipsis in case of C++11 + // note: the id must be unqualified then - TODO + if (_languageFeatures.cxx11Enabled && LA() == T_DOT_DOT_DOT) + ast->ellipsis_token = consumeToken(); + node = new (_pool) BaseSpecifierListAST; node->value = ast; return true; diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp index df29feeca94..f8a8440c097 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.cpp +++ b/src/libs/3rdparty/cplusplus/Symbols.cpp @@ -599,6 +599,12 @@ bool BaseClass::isVirtual() const void BaseClass::setVirtual(bool isVirtual) { _isVirtual = isVirtual; } +bool BaseClass::isVariadic() const +{ return _isVariadic; } + +void BaseClass::setVariadic(bool isVariadic) +{ _isVariadic = isVariadic; } + void BaseClass::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h index 79c0f01024f..257bdb86826 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.h +++ b/src/libs/3rdparty/cplusplus/Symbols.h @@ -474,6 +474,9 @@ public: bool isVirtual() const; void setVirtual(bool isVirtual); + bool isVariadic() const; + void setVariadic(bool isVariadic); + // Symbol's interface virtual FullySpecifiedType type() const; void setType(const FullySpecifiedType &type); @@ -488,6 +491,7 @@ protected: virtual void visitSymbol0(SymbolVisitor *visitor); private: + bool _isVariadic; bool _isVirtual; FullySpecifiedType _type; }; diff --git a/src/tools/cplusplus-ast2png/dumpers.inc b/src/tools/cplusplus-ast2png/dumpers.inc index 5e5bb1a10b7..aea2150a713 100644 --- a/src/tools/cplusplus-ast2png/dumpers.inc +++ b/src/tools/cplusplus-ast2png/dumpers.inc @@ -292,6 +292,8 @@ virtual bool visit(BaseSpecifierAST *ast) if (ast->access_specifier_token) terminal(ast->access_specifier_token, ast); nonterminal(ast->name); + if (ast->ellipsis_token) + terminal(ast->ellipsis_token, ast); return false; } diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 7b325ce4186..a2219e7cfc6 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -75,8 +75,10 @@ public: return unit; } - TranslationUnit *parseDeclaration(const QByteArray &source, bool blockErrors = false, bool qtMocRun = false) - { return parse(source, TranslationUnit::ParseDeclaration, blockErrors, qtMocRun); } + TranslationUnit *parseDeclaration(const QByteArray &source, bool blockErrors = false, + bool qtMocRun = false, bool cxx11Enabled = false) + { return parse(source, TranslationUnit::ParseDeclaration, + blockErrors, qtMocRun, cxx11Enabled); } TranslationUnit *parseExpression(const QByteArray &source) { return parse(source, TranslationUnit::ParseExpression); } @@ -167,6 +169,11 @@ private slots: void cpp_constructor_multiple_args(); void cpp_constructor_function_try_catch(); + // c++11 ast + //! checks for both correct ellipsis tokens in + //! "template class T : Args... {};" + void cpp11_variadic_inheritance(); + // Q_PROPERTY void cpp_qproperty(); void cpp_qproperty_data(); @@ -1273,6 +1280,49 @@ void tst_AST::cpp_constructor_function_try_catch() QVERIFY(funDecl->parameter_declaration_clause->parameter_declaration_list != 0); } +void tst_AST::cpp11_variadic_inheritance() +{ + QSharedPointer unit(parseDeclaration( + "template class C : public Args... {};", + false, false, true)); + AST *ast = unit->ast(); + QVERIFY(ast != 0); + + DeclarationAST *d = ast->asDeclaration(); + QVERIFY(d != 0); + + TemplateDeclarationAST *t = d->asTemplateDeclaration(); + QVERIFY(t != 0); + + DeclarationListAST *tp = t->template_parameter_list; + QVERIFY(tp != 0); + QVERIFY(tp->next == 0); + + DeclarationAST *d3 = tp->value; + QVERIFY(d3 != 0); + + TypenameTypeParameterAST *ttp = d3->asTypenameTypeParameter(); + QVERIFY(ttp != 0); + QVERIFY(ttp->dot_dot_dot_token != 0); // important + + DeclarationAST *d2 = t->declaration; + QVERIFY(d2 != 0); + + SimpleDeclarationAST *sd = d2->asSimpleDeclaration(); + QVERIFY(sd != 0); + + ClassSpecifierAST *cl = sd->decl_specifier_list->value->asClassSpecifier(); + QVERIFY(cl != 0); + + BaseSpecifierListAST *bl = cl->base_clause_list; + QVERIFY(bl != 0); + QVERIFY(bl->next == 0); + + BaseSpecifierAST *ba = bl->value; + QVERIFY(ba != 0); + QVERIFY(ba->ellipsis_token != 0); // important +} + void tst_AST::cpp_qproperty() { QFETCH(QByteArray, source);