Commit 080bf4ec authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski Committed by Erik Verbruggen
Browse files

C++: improve support for anonymous classes



Fix:
* highlighting
* find usages
* follow symbol
* code completion

Task-number: QTCREATORBUG-6497
Task-number: QTCREATORBUG-8963
Task-number: QTCREATORBUG-3610
Task-number: QTCREATORBUG-7579

Change-Id: I3dcaf1c515d0199c3e6bee72284fbb40064686ee
Reviewed-by: default avatarPetar Perisin <petar.perisin@gmail.com>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent a2b2857b
......@@ -127,6 +127,7 @@ public:
virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
virtual AliasDeclarationAST *asAliasDeclaration() { return 0; }
virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
virtual AnonymousNameAST *asAnonymousName() { return 0; }
virtual ArrayAccessAST *asArrayAccess() { return 0; }
virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
......@@ -2267,6 +2268,26 @@ protected:
virtual bool match0(AST *, ASTMatcher *);
};
class CPLUSPLUS_EXPORT AnonymousNameAST: public NameAST
{
public:
unsigned class_token;
public:
AnonymousNameAST()
: class_token(0)
{}
virtual AnonymousNameAST *asAnonymousName() { return this; }
virtual unsigned firstToken() const { return 0; }
virtual unsigned lastToken() const { return 0; }
virtual AnonymousNameAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST
{
public:
......
......@@ -824,6 +824,13 @@ ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
return ast;
}
AnonymousNameAST *AnonymousNameAST::clone(MemoryPool *pool) const
{
AnonymousNameAST *ast = new (pool) AnonymousNameAST;
ast->class_token = class_token;
return ast;
}
SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
{
SimpleNameAST *ast = new (pool) SimpleNameAST;
......
......@@ -552,6 +552,14 @@ bool ConversionFunctionIdAST::match0(AST *pattern, ASTMatcher *matcher)
return false;
}
bool AnonymousNameAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (AnonymousNameAST *_other = pattern->asAnonymousName())
return matcher->match(this, _other);
return false;
}
bool SimpleNameAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (SimpleNameAST *_other = pattern->asSimpleName())
......
......@@ -1403,6 +1403,16 @@ bool ASTMatcher::match(ConversionFunctionIdAST *node, ConversionFunctionIdAST *p
return true;
}
bool ASTMatcher::match(AnonymousNameAST *node, AnonymousNameAST *pattern)
{
(void) node;
(void) pattern;
pattern->class_token = node->class_token;
return true;
}
bool ASTMatcher::match(SimpleNameAST *node, SimpleNameAST *pattern)
{
(void) node;
......
......@@ -34,6 +34,7 @@ public:
virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
virtual bool match(AliasDeclarationAST *node, AliasDeclarationAST *pattern);
virtual bool match(AlignofExpressionAST *node, AlignofExpressionAST *pattern);
virtual bool match(AnonymousNameAST *node, AnonymousNameAST *pattern);
virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern);
virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
......
......@@ -543,6 +543,12 @@ public:
return __ast;
}
AnonymousNameAST *AnonymousName()
{
AnonymousNameAST *__ast = new (&pool) AnonymousNameAST;
return __ast;
}
SimpleNameAST *SimpleName()
{
SimpleNameAST *__ast = new (&pool) SimpleNameAST;
......
......@@ -596,6 +596,13 @@ void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this);
}
void AnonymousNameAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void SimpleNameAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
......
......@@ -76,6 +76,7 @@ public:
virtual bool visit(AccessDeclarationAST *) { return true; }
virtual bool visit(AliasDeclarationAST *) { return true; }
virtual bool visit(AlignofExpressionAST *) { return true; }
virtual bool visit(AnonymousNameAST *) { return true; }
virtual bool visit(ArrayAccessAST *) { return true; }
virtual bool visit(ArrayDeclaratorAST *) { return true; }
virtual bool visit(ArrayInitializerAST *) { return true; }
......@@ -221,6 +222,7 @@ public:
virtual void endVisit(AccessDeclarationAST *) {}
virtual void endVisit(AliasDeclarationAST *) {}
virtual void endVisit(AlignofExpressionAST *) {}
virtual void endVisit(AnonymousNameAST *) {}
virtual void endVisit(ArrayAccessAST *) {}
virtual void endVisit(ArrayDeclaratorAST *) {}
virtual void endVisit(ArrayInitializerAST *) {}
......
......@@ -34,6 +34,7 @@ class ASTMatcher;
class AccessDeclarationAST;
class AliasDeclarationAST;
class AlignofExpressionAST;
class AnonymousNameAST;
class ArrayAccessAST;
class ArrayDeclaratorAST;
class ArrayInitializerAST;
......
......@@ -2614,6 +2614,12 @@ bool Bind::visit(ConversionFunctionIdAST *ast)
return false;
}
bool Bind::visit(AnonymousNameAST *ast)
{
ast->name = _name = control()->anonymousNameId(ast->class_token);
return false;
}
bool Bind::visit(SimpleNameAST *ast)
{
const Identifier *id = identifier(ast->identifier_token);
......@@ -2896,7 +2902,7 @@ bool Bind::visit(ClassSpecifierAST *ast)
const Name *className = this->name(ast->name);
if (ast->name) {
if (ast->name && ! ast->name->asAnonymousName()) {
sourceLocation = location(ast->name, sourceLocation);
startScopeOffset = tokenAt(sourceLocation).end(); // at the end of the class name
......
......@@ -237,6 +237,7 @@ protected:
virtual bool visit(QualifiedNameAST *ast);
virtual bool visit(OperatorFunctionIdAST *ast);
virtual bool visit(ConversionFunctionIdAST *ast);
virtual bool visit(AnonymousNameAST *ast);
virtual bool visit(SimpleNameAST *ast);
virtual bool visit(DestructorNameAST *ast);
virtual bool visit(TemplateIdAST *ast);
......
......@@ -73,6 +73,7 @@ class SymbolTable;
class NameVisitor;
class Name;
class Identifier;
class AnonymousNameId;
class TemplateNameId;
class DestructorNameId;
class OperatorNameId;
......
......@@ -101,6 +101,14 @@ template <> struct Compare<ArrayType>
}
};
template <> struct Compare<AnonymousNameId>
{
bool operator()(const AnonymousNameId &name, const AnonymousNameId &otherName) const
{
return name.classTokenIndex() < otherName.classTokenIndex();
}
};
template <> struct Compare<DestructorNameId>
{
bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const
......@@ -219,6 +227,11 @@ public:
delete_array_entries(symbols);
}
const AnonymousNameId *findOrInsertAnonymousNameId(unsigned classTokenIndex)
{
return anonymousNameIds.intern(AnonymousNameId(classTokenIndex));
}
template <typename _Iterator>
const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, bool isSpecialization,
_Iterator first, _Iterator last)
......@@ -475,6 +488,7 @@ public:
// ### replace std::map with lookup tables. ASAP!
// names
Table<AnonymousNameId> anonymousNameIds;
Table<DestructorNameId> destructorNameIds;
Table<OperatorNameId> operatorNameIds;
Table<ConversionNameId> conversionNameIds;
......@@ -550,6 +564,9 @@ DiagnosticClient *Control::diagnosticClient() const
void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
{ d->diagnosticClient = diagnosticClient; }
const AnonymousNameId *Control::anonymousNameId(unsigned classTokenIndex)
{ return d->findOrInsertAnonymousNameId(classTokenIndex); }
const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
{
Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
......
......@@ -49,6 +49,9 @@ public:
DiagnosticClient *diagnosticClient() const;
void setDiagnosticClient(DiagnosticClient *diagnosticClient);
/// Returns the canonical anonymous name id
const AnonymousNameId *anonymousNameId(unsigned classTokenIndex);
/// Returns the canonical template name id.
const TemplateNameId *templateNameId(const Identifier *id,
bool isSpecialization,
......
......@@ -36,6 +36,9 @@ Name::~Name()
bool Name::isNameId() const
{ return asNameId() != 0; }
bool Name::isAnonymousNameId() const
{ return asAnonymousNameId() != 0; }
bool Name::isTemplateNameId() const
{ return asTemplateNameId() != 0; }
......
......@@ -36,6 +36,7 @@ public:
virtual const Identifier *identifier() const = 0;
bool isNameId() const;
bool isAnonymousNameId() const;
bool isTemplateNameId() const;
bool isDestructorNameId() const;
bool isOperatorNameId() const;
......@@ -44,6 +45,7 @@ public:
bool isSelectorNameId() const;
virtual const Identifier *asNameId() const { return 0; }
virtual const AnonymousNameId *asAnonymousNameId() const { return 0; }
virtual const TemplateNameId *asTemplateNameId() const { return 0; }
virtual const DestructorNameId *asDestructorNameId() const { return 0; }
virtual const OperatorNameId *asOperatorNameId() const { return 0; }
......
......@@ -40,6 +40,7 @@ public:
virtual bool preVisit(const Name *) { return true; }
virtual void postVisit(const Name *) {}
virtual void visit(const AnonymousNameId *) {}
virtual void visit(const Identifier *) {}
virtual void visit(const TemplateNameId *) {}
virtual void visit(const DestructorNameId *) {}
......
......@@ -249,3 +249,29 @@ bool SelectorNameId::isEqualTo(const Name *other) const
return true;
}
AnonymousNameId::AnonymousNameId(unsigned classTokenIndex)
: _classTokenIndex(classTokenIndex)
{ }
AnonymousNameId::~AnonymousNameId()
{ }
unsigned AnonymousNameId::classTokenIndex() const
{
return _classTokenIndex;
}
void AnonymousNameId::accept0(NameVisitor *visitor) const
{ visitor->visit(this); }
const Identifier *AnonymousNameId::identifier() const
{ return 0; }
bool AnonymousNameId::isEqualTo(const Name *other) const
{
if (other) {
const AnonymousNameId *c = other->asAnonymousNameId();
return (c && this->_classTokenIndex == c->_classTokenIndex);
}
return false;
}
......@@ -253,6 +253,29 @@ private:
bool _hasArguments;
};
class CPLUSPLUS_EXPORT AnonymousNameId: public Name
{
public:
AnonymousNameId(unsigned classTokenIndex);
virtual ~AnonymousNameId();
unsigned classTokenIndex() const;
virtual const Identifier *identifier() const;
virtual bool isEqualTo(const Name *other) const;
virtual const AnonymousNameId *asAnonymousNameId() const
{ return this; }
protected:
virtual void accept0(NameVisitor *visitor) const;
private:
unsigned _classTokenIndex;
};
} // namespace CPlusPlus
#endif // CPLUSPLUS_NAMES_H
......@@ -2003,6 +2003,12 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node)
NameAST *name = 0;
parseName(name);
if (! name && LA() == T_LBRACE && (LA(0) == T_CLASS || LA(0) == T_STRUCT || LA(0) == T_UNION || LA(0) == T_ENUM)) {
AnonymousNameAST *ast = new (_pool) AnonymousNameAST;
ast->class_token = classkey_token;
name = ast;
}
bool parsed = false;
const bool previousInFunctionBody = _inFunctionBody;
......
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