Commit 368d5926 authored by Erik Verbruggen's avatar Erik Verbruggen

C++: handle destructor names with template parameters.

Change-Id: I74b4fd5e043db935abc18345b303d294b71e8fc2
Reviewed-by: default avatarTobias Hunger <tobias.hunger@nokia.com>
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@nokia.com>
parent c9999a93
...@@ -963,16 +963,18 @@ unsigned DestructorNameAST::firstToken() const ...@@ -963,16 +963,18 @@ unsigned DestructorNameAST::firstToken() const
{ {
if (tilde_token) if (tilde_token)
return tilde_token; return tilde_token;
if (identifier_token) if (unqualified_name)
return identifier_token; if (unsigned candidate = unqualified_name->firstToken())
return candidate;
return 0; return 0;
} }
/** \generated */ /** \generated */
unsigned DestructorNameAST::lastToken() const unsigned DestructorNameAST::lastToken() const
{ {
if (identifier_token) if (unqualified_name)
return identifier_token + 1; if (unsigned candidate = unqualified_name->lastToken())
return candidate;
if (tilde_token) if (tilde_token)
return tilde_token + 1; return tilde_token + 1;
return 1; return 1;
......
...@@ -2286,12 +2286,12 @@ class CPLUSPLUS_EXPORT DestructorNameAST: public NameAST ...@@ -2286,12 +2286,12 @@ class CPLUSPLUS_EXPORT DestructorNameAST: public NameAST
{ {
public: public:
unsigned tilde_token; unsigned tilde_token;
unsigned identifier_token; NameAST *unqualified_name;
public: public:
DestructorNameAST() DestructorNameAST()
: tilde_token(0) : tilde_token(0)
, identifier_token(0) , unqualified_name(0)
{} {}
virtual DestructorNameAST *asDestructorName() { return this; } virtual DestructorNameAST *asDestructorName() { return this; }
......
...@@ -833,7 +833,8 @@ DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const ...@@ -833,7 +833,8 @@ DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const
{ {
DestructorNameAST *ast = new (pool) DestructorNameAST; DestructorNameAST *ast = new (pool) DestructorNameAST;
ast->tilde_token = tilde_token; ast->tilde_token = tilde_token;
ast->identifier_token = identifier_token; if (unqualified_name)
ast->unqualified_name = unqualified_name->clone(pool);
return ast; return ast;
} }
......
...@@ -1416,7 +1416,10 @@ bool ASTMatcher::match(DestructorNameAST *node, DestructorNameAST *pattern) ...@@ -1416,7 +1416,10 @@ bool ASTMatcher::match(DestructorNameAST *node, DestructorNameAST *pattern)
pattern->tilde_token = node->tilde_token; pattern->tilde_token = node->tilde_token;
pattern->identifier_token = node->identifier_token; if (! pattern->unqualified_name)
pattern->unqualified_name = node->unqualified_name;
else if (! AST::match(node->unqualified_name, pattern->unqualified_name, this))
return false;
return true; return true;
} }
......
...@@ -549,9 +549,10 @@ public: ...@@ -549,9 +549,10 @@ public:
return __ast; return __ast;
} }
DestructorNameAST *DestructorName() DestructorNameAST *DestructorName(NameAST *unqualified_name = 0)
{ {
DestructorNameAST *__ast = new (&pool) DestructorNameAST; DestructorNameAST *__ast = new (&pool) DestructorNameAST;
__ast->unqualified_name = unqualified_name;
return __ast; return __ast;
} }
......
...@@ -606,6 +606,7 @@ void SimpleNameAST::accept0(ASTVisitor *visitor) ...@@ -606,6 +606,7 @@ void SimpleNameAST::accept0(ASTVisitor *visitor)
void DestructorNameAST::accept0(ASTVisitor *visitor) void DestructorNameAST::accept0(ASTVisitor *visitor)
{ {
if (visitor->visit(this)) { if (visitor->visit(this)) {
accept(unqualified_name, visitor);
} }
visitor->endVisit(this); visitor->endVisit(this);
} }
......
...@@ -91,7 +91,7 @@ unsigned Bind::location(NameAST *name, unsigned defaultLocation) const ...@@ -91,7 +91,7 @@ unsigned Bind::location(NameAST *name, unsigned defaultLocation) const
return defaultLocation; return defaultLocation;
else if (DestructorNameAST *dtor = name->asDestructorName()) else if (DestructorNameAST *dtor = name->asDestructorName())
return dtor->identifier_token; return location(dtor->unqualified_name, defaultLocation);
else if (TemplateIdAST *templId = name->asTemplateId()) else if (TemplateIdAST *templId = name->asTemplateId())
return templId->identifier_token; return templId->identifier_token;
...@@ -2624,8 +2624,7 @@ bool Bind::visit(SimpleNameAST *ast) ...@@ -2624,8 +2624,7 @@ bool Bind::visit(SimpleNameAST *ast)
bool Bind::visit(DestructorNameAST *ast) bool Bind::visit(DestructorNameAST *ast)
{ {
const Identifier *id = identifier(ast->identifier_token); _name = control()->destructorNameId(name(ast->unqualified_name));
_name = control()->destructorNameId(id);
ast->name = _name; ast->name = _name;
return false; return false;
} }
......
...@@ -227,9 +227,9 @@ public: ...@@ -227,9 +227,9 @@ public:
return templateNameIds.intern(TemplateNameId(id, first, last)); return templateNameIds.intern(TemplateNameId(id, first, last));
} }
const DestructorNameId *findOrInsertDestructorNameId(const Identifier *id) const DestructorNameId *findOrInsertDestructorNameId(const Name *name)
{ {
return destructorNameIds.intern(DestructorNameId(id)); return destructorNameIds.intern(DestructorNameId(name));
} }
const OperatorNameId *findOrInsertOperatorNameId(OperatorNameId::Kind kind) const OperatorNameId *findOrInsertOperatorNameId(OperatorNameId::Kind kind)
...@@ -610,8 +610,8 @@ const TemplateNameId *Control::templateNameId(const Identifier *id, ...@@ -610,8 +610,8 @@ const TemplateNameId *Control::templateNameId(const Identifier *id,
return d->findOrInsertTemplateNameId(id, args, args + argv); return d->findOrInsertTemplateNameId(id, args, args + argv);
} }
const DestructorNameId *Control::destructorNameId(const Identifier *id) const DestructorNameId *Control::destructorNameId(const Name *name)
{ return d->findOrInsertDestructorNameId(id); } { return d->findOrInsertDestructorNameId(name); }
const OperatorNameId *Control::operatorNameId(OperatorNameId::Kind kind) const OperatorNameId *Control::operatorNameId(OperatorNameId::Kind kind)
{ return d->findOrInsertOperatorNameId(kind); } { return d->findOrInsertOperatorNameId(kind); }
......
...@@ -55,7 +55,7 @@ public: ...@@ -55,7 +55,7 @@ public:
unsigned argc = 0); unsigned argc = 0);
/// Returns the canonical destructor name id. /// Returns the canonical destructor name id.
const DestructorNameId *destructorNameId(const Identifier *id); const DestructorNameId *destructorNameId(const Name *name);
/// Returns the canonical operator name id. /// Returns the canonical operator name id.
const OperatorNameId *operatorNameId(OperatorNameId::Kind operatorId); const OperatorNameId *operatorNameId(OperatorNameId::Kind operatorId);
......
...@@ -62,8 +62,8 @@ bool QualifiedNameId::isEqualTo(const Name *other) const ...@@ -62,8 +62,8 @@ bool QualifiedNameId::isEqualTo(const Name *other) const
return false; return false;
} }
DestructorNameId::DestructorNameId(const Identifier *identifier) DestructorNameId::DestructorNameId(const Name *name)
: _identifier(identifier) : _name(name)
{ } { }
DestructorNameId::~DestructorNameId() DestructorNameId::~DestructorNameId()
...@@ -72,8 +72,11 @@ DestructorNameId::~DestructorNameId() ...@@ -72,8 +72,11 @@ DestructorNameId::~DestructorNameId()
void DestructorNameId::accept0(NameVisitor *visitor) const void DestructorNameId::accept0(NameVisitor *visitor) const
{ visitor->visit(this); } { visitor->visit(this); }
const Name *DestructorNameId::name() const
{ return _name; }
const Identifier *DestructorNameId::identifier() const const Identifier *DestructorNameId::identifier() const
{ return _identifier; } { return _name->identifier(); }
bool DestructorNameId::isEqualTo(const Name *other) const bool DestructorNameId::isEqualTo(const Name *other) const
{ {
...@@ -81,8 +84,8 @@ bool DestructorNameId::isEqualTo(const Name *other) const ...@@ -81,8 +84,8 @@ bool DestructorNameId::isEqualTo(const Name *other) const
const DestructorNameId *d = other->asDestructorNameId(); const DestructorNameId *d = other->asDestructorNameId();
if (! d) if (! d)
return false; return false;
const Identifier *l = identifier(); const Name *l = name();
const Identifier *r = d->identifier(); const Name *r = d->name();
return l->isEqualTo(r); return l->isEqualTo(r);
} }
return false; return false;
......
...@@ -57,9 +57,11 @@ private: ...@@ -57,9 +57,11 @@ private:
class CPLUSPLUS_EXPORT DestructorNameId: public Name class CPLUSPLUS_EXPORT DestructorNameId: public Name
{ {
public: public:
DestructorNameId(const Identifier *identifier); DestructorNameId(const Name *name);
virtual ~DestructorNameId(); virtual ~DestructorNameId();
virtual const Name *name() const;
virtual const Identifier *identifier() const; virtual const Identifier *identifier() const;
virtual bool isEqualTo(const Name *other) const; virtual bool isEqualTo(const Name *other) const;
...@@ -71,7 +73,7 @@ protected: ...@@ -71,7 +73,7 @@ protected:
virtual void accept0(NameVisitor *visitor) const; virtual void accept0(NameVisitor *visitor) const;
private: private:
const Identifier *_identifier; const Name *_name;
}; };
class CPLUSPLUS_EXPORT TemplateNameId: public Name class CPLUSPLUS_EXPORT TemplateNameId: public Name
......
...@@ -2740,7 +2740,7 @@ bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId) ...@@ -2740,7 +2740,7 @@ bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId)
if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) { if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) {
DestructorNameAST *ast = new (_pool) DestructorNameAST; DestructorNameAST *ast = new (_pool) DestructorNameAST;
ast->tilde_token = consumeToken(); ast->tilde_token = consumeToken();
ast->identifier_token = consumeToken(); parseUnqualifiedName(ast->unqualified_name);
node = ast; node = ast;
return true; return true;
} else if (LA() == T_OPERATOR) { } else if (LA() == T_OPERATOR) {
......
...@@ -1945,9 +1945,6 @@ bool FindUsages::visit(QualifiedNameAST *ast) ...@@ -1945,9 +1945,6 @@ bool FindUsages::visit(QualifiedNameAST *ast)
if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) if (SimpleNameAST *simple_name = unqualified_name->asSimpleName())
identifier_token = simple_name->identifier_token; identifier_token = simple_name->identifier_token;
else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName())
identifier_token = dtor_name->identifier_token;
TemplateIdAST *template_id = 0; TemplateIdAST *template_id = 0;
if (! identifier_token) { if (! identifier_token) {
template_id = unqualified_name->asTemplateId(); template_id = unqualified_name->asTemplateId();
...@@ -1997,14 +1994,6 @@ bool FindUsages::visit(SimpleNameAST *ast) ...@@ -1997,14 +1994,6 @@ bool FindUsages::visit(SimpleNameAST *ast)
return false; return false;
} }
bool FindUsages::visit(DestructorNameAST *ast)
{
// unsigned tilde_token = ast->tilde_token;
// unsigned identifier_token = ast->identifier_token;
reportResult(ast->identifier_token, ast->name);
return false;
}
bool FindUsages::visit(TemplateIdAST *ast) bool FindUsages::visit(TemplateIdAST *ast)
{ {
// unsigned identifier_token = ast->identifier_token; // unsigned identifier_token = ast->identifier_token;
......
...@@ -259,7 +259,6 @@ protected: ...@@ -259,7 +259,6 @@ protected:
virtual bool visit(OperatorFunctionIdAST *ast); virtual bool visit(OperatorFunctionIdAST *ast);
virtual bool visit(ConversionFunctionIdAST *ast); virtual bool visit(ConversionFunctionIdAST *ast);
virtual bool visit(SimpleNameAST *ast); virtual bool visit(SimpleNameAST *ast);
virtual bool visit(DestructorNameAST *ast);
virtual bool visit(TemplateIdAST *ast); virtual bool visit(TemplateIdAST *ast);
// SpecifierAST // SpecifierAST
......
...@@ -829,6 +829,8 @@ void CheckSymbols::addUse(NameAST *ast, UseKind kind) ...@@ -829,6 +829,8 @@ void CheckSymbols::addUse(NameAST *ast, UseKind kind)
if (QualifiedNameAST *q = ast->asQualifiedName()) if (QualifiedNameAST *q = ast->asQualifiedName())
ast = q->unqualified_name; ast = q->unqualified_name;
if (DestructorNameAST *dtor = ast->asDestructorName())
ast = dtor->unqualified_name;
if (! ast) if (! ast)
return; // nothing to do return; // nothing to do
...@@ -837,10 +839,7 @@ void CheckSymbols::addUse(NameAST *ast, UseKind kind) ...@@ -837,10 +839,7 @@ void CheckSymbols::addUse(NameAST *ast, UseKind kind)
unsigned startToken = ast->firstToken(); unsigned startToken = ast->firstToken();
if (DestructorNameAST *dtor = ast->asDestructorName()) if (TemplateIdAST *templ = ast->asTemplateId())
startToken = dtor->identifier_token;
else if (TemplateIdAST *templ = ast->asTemplateId())
startToken = templ->identifier_token; startToken = templ->identifier_token;
addUse(startToken, kind); addUse(startToken, kind);
...@@ -888,7 +887,8 @@ void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast) ...@@ -888,7 +887,8 @@ void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
unsigned startToken = ast->firstToken(); unsigned startToken = ast->firstToken();
if (DestructorNameAST *dtor = ast->asDestructorName()) if (DestructorNameAST *dtor = ast->asDestructorName())
startToken = dtor->identifier_token; if (dtor->unqualified_name)
startToken = dtor->unqualified_name->firstToken();
const Token &tok = tokenAt(startToken); const Token &tok = tokenAt(startToken);
if (tok.generated()) if (tok.generated())
...@@ -919,7 +919,8 @@ void CheckSymbols::addTypeOrStatic(const QList<LookupItem> &candidates, NameAST ...@@ -919,7 +919,8 @@ void CheckSymbols::addTypeOrStatic(const QList<LookupItem> &candidates, NameAST
{ {
unsigned startToken = ast->firstToken(); unsigned startToken = ast->firstToken();
if (DestructorNameAST *dtor = ast->asDestructorName()) if (DestructorNameAST *dtor = ast->asDestructorName())
startToken = dtor->identifier_token; if (dtor->unqualified_name)
startToken = dtor->unqualified_name->firstToken();
const Token &tok = tokenAt(startToken); const Token &tok = tokenAt(startToken);
if (tok.generated()) if (tok.generated())
...@@ -956,7 +957,8 @@ void CheckSymbols::addClassMember(const QList<LookupItem> &candidates, NameAST * ...@@ -956,7 +957,8 @@ void CheckSymbols::addClassMember(const QList<LookupItem> &candidates, NameAST *
{ {
unsigned startToken = ast->firstToken(); unsigned startToken = ast->firstToken();
if (DestructorNameAST *dtor = ast->asDestructorName()) if (DestructorNameAST *dtor = ast->asDestructorName())
startToken = dtor->identifier_token; if (dtor->unqualified_name)
startToken = dtor->unqualified_name->firstToken();
const Token &tok = tokenAt(startToken); const Token &tok = tokenAt(startToken);
if (tok.generated()) if (tok.generated())
...@@ -1014,7 +1016,8 @@ void CheckSymbols::addVirtualMethod(const QList<LookupItem> &candidates, NameAST ...@@ -1014,7 +1016,8 @@ void CheckSymbols::addVirtualMethod(const QList<LookupItem> &candidates, NameAST
{ {
unsigned startToken = ast->firstToken(); unsigned startToken = ast->firstToken();
if (DestructorNameAST *dtor = ast->asDestructorName()) if (DestructorNameAST *dtor = ast->asDestructorName())
startToken = dtor->identifier_token; if (dtor->unqualified_name)
startToken = dtor->unqualified_name->firstToken();
const Token &tok = tokenAt(startToken); const Token &tok = tokenAt(startToken);
if (tok.generated()) if (tok.generated())
......
...@@ -109,6 +109,11 @@ private slots: ...@@ -109,6 +109,11 @@ private slots:
void init_1(); void init_1();
void conditional_1(); void conditional_1();
void throw_1(); void throw_1();
void templated_dtor_1();
void templated_dtor_2();
void templated_dtor_3();
void templated_dtor_4();
void templated_dtor_5();
// possible declaration-or-expression statements // possible declaration-or-expression statements
void call_call_1(); void call_call_1();
...@@ -415,6 +420,229 @@ void tst_AST::throw_1() ...@@ -415,6 +420,229 @@ void tst_AST::throw_1()
QVERIFY(ast->asExpressionStatement()); QVERIFY(ast->asExpressionStatement());
} }
void tst_AST::templated_dtor_1()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a.b::~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
MemberAccessAST *mem = call->base_expression->asMemberAccess();
QVERIFY(mem);
QCOMPARE(unit->spell(mem->base_expression->asIdExpression()->name->asSimpleName()->identifier_token), "a");
QualifiedNameAST *qName = mem->member_name->asQualifiedName();
QVERIFY(qName);
QVERIFY(qName->nested_name_specifier_list);
QVERIFY(!qName->nested_name_specifier_list->next);
QVERIFY(qName->nested_name_specifier_list->value);
QVERIFY(qName->nested_name_specifier_list->value->class_or_namespace_name);
SimpleNameAST *bName = qName->nested_name_specifier_list->value->class_or_namespace_name->asSimpleName();
QVERIFY(bName);
QCOMPARE(unit->spell(bName->identifier_token), "b");
QVERIFY(qName->unqualified_name);
DestructorNameAST *dtor = qName->unqualified_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_2()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a.~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
MemberAccessAST *mem = call->base_expression->asMemberAccess();
QVERIFY(mem);
QCOMPARE(unit->spell(mem->base_expression->asIdExpression()->name->asSimpleName()->identifier_token), "a");
QVERIFY(mem->member_name);
DestructorNameAST *dtor = mem->member_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_3()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"a::~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();
QVERIFY(e);
QVERIFY(e->expression);
CallAST *call = e->expression->asCall();
QVERIFY(call);
QVERIFY(!call->expression_list);
QVERIFY(call->base_expression);
IdExpressionAST *idExpr = call->base_expression->asIdExpression();
QVERIFY(idExpr);
QVERIFY(idExpr->name);
QualifiedNameAST *qName = idExpr->name->asQualifiedName();
QVERIFY(qName);
QVERIFY(qName->nested_name_specifier_list);
QVERIFY(!qName->nested_name_specifier_list->next);
QVERIFY(qName->nested_name_specifier_list->value);
QVERIFY(qName->nested_name_specifier_list->value->class_or_namespace_name);
SimpleNameAST *bName = qName->nested_name_specifier_list->value->class_or_namespace_name->asSimpleName();
QVERIFY(bName);
QCOMPARE(unit->spell(bName->identifier_token), "a");
QVERIFY(qName->unqualified_name);
DestructorNameAST *dtor = qName->unqualified_name->asDestructorName();
QVERIFY(dtor);
QVERIFY(dtor->unqualified_name);
TemplateIdAST *tid = dtor->unqualified_name->asTemplateId();
QVERIFY(tid);
QCOMPARE(unit->spell(tid->identifier_token), "b");
QVERIFY(tid->template_argument_list);
QVERIFY(!tid->template_argument_list->next);
QVERIFY(tid->template_argument_list->value);
TypeIdAST *typeId = tid->template_argument_list->value->asTypeId();
QVERIFY(typeId);
QVERIFY(!typeId->declarator);
QVERIFY(typeId->type_specifier_list);
QVERIFY(!typeId->type_specifier_list->next);
QVERIFY(typeId->type_specifier_list->value);
NamedTypeSpecifierAST *nts = typeId->type_specifier_list->value->asNamedTypeSpecifier();
QVERIFY(nts);
QVERIFY(nts->name);
SimpleNameAST *cName = nts->name->asSimpleName();
QVERIFY(cName);
QCOMPARE(unit->spell(cName->identifier_token), "c");
}
void tst_AST::templated_dtor_4()
{
QSharedPointer<TranslationUnit> unit(parseStatement(
"\n"
"~b<c>();"
));
AST *ast = unit->ast();
QVERIFY(ast != 0);
ExpressionStatementAST *e = ast->asExpressionStatement();