Commit 2a966a89 authored by Johannes Lorenz's avatar Johannes Lorenz Committed by Orgad Shaneh

C++: Support ellipsis on variadic inheritance parsing

Change-Id: I571aefdb1f2aba88ba0c7710f16b6d8ad2e8f5a8
Reviewed-by: default avatarAndré Hartmann <aha_1980@gmx.de>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent 69747957
......@@ -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;
......
......@@ -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)
{}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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); }
......
......@@ -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;
};
......
......@@ -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;
}
......
......@@ -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 ...Args> 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<TranslationUnit> unit(parseDeclaration(
"template<class ...Args> 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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment