forked from qt-creator/qt-creator
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: Petar Perisin <petar.perisin@gmail.com> Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
a2b2857b44
commit
080bf4ecb8
21
src/libs/3rdparty/cplusplus/AST.h
vendored
21
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -127,6 +127,7 @@ public:
|
|||||||
virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
|
virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
|
||||||
virtual AliasDeclarationAST *asAliasDeclaration() { return 0; }
|
virtual AliasDeclarationAST *asAliasDeclaration() { return 0; }
|
||||||
virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
|
virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
|
||||||
|
virtual AnonymousNameAST *asAnonymousName() { return 0; }
|
||||||
virtual ArrayAccessAST *asArrayAccess() { return 0; }
|
virtual ArrayAccessAST *asArrayAccess() { return 0; }
|
||||||
virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
|
virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
|
||||||
virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
|
virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
|
||||||
@@ -2267,6 +2268,26 @@ protected:
|
|||||||
virtual bool match0(AST *, ASTMatcher *);
|
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
|
class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
7
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -824,6 +824,13 @@ ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
|
|||||||
return ast;
|
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 *SimpleNameAST::clone(MemoryPool *pool) const
|
||||||
{
|
{
|
||||||
SimpleNameAST *ast = new (pool) SimpleNameAST;
|
SimpleNameAST *ast = new (pool) SimpleNameAST;
|
||||||
|
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -552,6 +552,14 @@ bool ConversionFunctionIdAST::match0(AST *pattern, ASTMatcher *matcher)
|
|||||||
return false;
|
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)
|
bool SimpleNameAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||||
{
|
{
|
||||||
if (SimpleNameAST *_other = pattern->asSimpleName())
|
if (SimpleNameAST *_other = pattern->asSimpleName())
|
||||||
|
10
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
10
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -1403,6 +1403,16 @@ bool ASTMatcher::match(ConversionFunctionIdAST *node, ConversionFunctionIdAST *p
|
|||||||
return true;
|
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)
|
bool ASTMatcher::match(SimpleNameAST *node, SimpleNameAST *pattern)
|
||||||
{
|
{
|
||||||
(void) node;
|
(void) node;
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -34,6 +34,7 @@ public:
|
|||||||
virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
|
virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
|
||||||
virtual bool match(AliasDeclarationAST *node, AliasDeclarationAST *pattern);
|
virtual bool match(AliasDeclarationAST *node, AliasDeclarationAST *pattern);
|
||||||
virtual bool match(AlignofExpressionAST *node, AlignofExpressionAST *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(ArrayAccessAST *node, ArrayAccessAST *pattern);
|
||||||
virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
|
virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
|
||||||
virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
|
virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
|
||||||
|
@@ -543,6 +543,12 @@ public:
|
|||||||
return __ast;
|
return __ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnonymousNameAST *AnonymousName()
|
||||||
|
{
|
||||||
|
AnonymousNameAST *__ast = new (&pool) AnonymousNameAST;
|
||||||
|
return __ast;
|
||||||
|
}
|
||||||
|
|
||||||
SimpleNameAST *SimpleName()
|
SimpleNameAST *SimpleName()
|
||||||
{
|
{
|
||||||
SimpleNameAST *__ast = new (&pool) SimpleNameAST;
|
SimpleNameAST *__ast = new (&pool) SimpleNameAST;
|
||||||
|
7
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -596,6 +596,13 @@ void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
|
|||||||
visitor->endVisit(this);
|
visitor->endVisit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnonymousNameAST::accept0(ASTVisitor *visitor)
|
||||||
|
{
|
||||||
|
if (visitor->visit(this)) {
|
||||||
|
}
|
||||||
|
visitor->endVisit(this);
|
||||||
|
}
|
||||||
|
|
||||||
void SimpleNameAST::accept0(ASTVisitor *visitor)
|
void SimpleNameAST::accept0(ASTVisitor *visitor)
|
||||||
{
|
{
|
||||||
if (visitor->visit(this)) {
|
if (visitor->visit(this)) {
|
||||||
|
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -76,6 +76,7 @@ public:
|
|||||||
virtual bool visit(AccessDeclarationAST *) { return true; }
|
virtual bool visit(AccessDeclarationAST *) { return true; }
|
||||||
virtual bool visit(AliasDeclarationAST *) { return true; }
|
virtual bool visit(AliasDeclarationAST *) { return true; }
|
||||||
virtual bool visit(AlignofExpressionAST *) { return true; }
|
virtual bool visit(AlignofExpressionAST *) { return true; }
|
||||||
|
virtual bool visit(AnonymousNameAST *) { return true; }
|
||||||
virtual bool visit(ArrayAccessAST *) { return true; }
|
virtual bool visit(ArrayAccessAST *) { return true; }
|
||||||
virtual bool visit(ArrayDeclaratorAST *) { return true; }
|
virtual bool visit(ArrayDeclaratorAST *) { return true; }
|
||||||
virtual bool visit(ArrayInitializerAST *) { return true; }
|
virtual bool visit(ArrayInitializerAST *) { return true; }
|
||||||
@@ -221,6 +222,7 @@ public:
|
|||||||
virtual void endVisit(AccessDeclarationAST *) {}
|
virtual void endVisit(AccessDeclarationAST *) {}
|
||||||
virtual void endVisit(AliasDeclarationAST *) {}
|
virtual void endVisit(AliasDeclarationAST *) {}
|
||||||
virtual void endVisit(AlignofExpressionAST *) {}
|
virtual void endVisit(AlignofExpressionAST *) {}
|
||||||
|
virtual void endVisit(AnonymousNameAST *) {}
|
||||||
virtual void endVisit(ArrayAccessAST *) {}
|
virtual void endVisit(ArrayAccessAST *) {}
|
||||||
virtual void endVisit(ArrayDeclaratorAST *) {}
|
virtual void endVisit(ArrayDeclaratorAST *) {}
|
||||||
virtual void endVisit(ArrayInitializerAST *) {}
|
virtual void endVisit(ArrayInitializerAST *) {}
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -34,6 +34,7 @@ class ASTMatcher;
|
|||||||
class AccessDeclarationAST;
|
class AccessDeclarationAST;
|
||||||
class AliasDeclarationAST;
|
class AliasDeclarationAST;
|
||||||
class AlignofExpressionAST;
|
class AlignofExpressionAST;
|
||||||
|
class AnonymousNameAST;
|
||||||
class ArrayAccessAST;
|
class ArrayAccessAST;
|
||||||
class ArrayDeclaratorAST;
|
class ArrayDeclaratorAST;
|
||||||
class ArrayInitializerAST;
|
class ArrayInitializerAST;
|
||||||
|
8
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
8
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -2614,6 +2614,12 @@ bool Bind::visit(ConversionFunctionIdAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Bind::visit(AnonymousNameAST *ast)
|
||||||
|
{
|
||||||
|
ast->name = _name = control()->anonymousNameId(ast->class_token);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Bind::visit(SimpleNameAST *ast)
|
bool Bind::visit(SimpleNameAST *ast)
|
||||||
{
|
{
|
||||||
const Identifier *id = identifier(ast->identifier_token);
|
const Identifier *id = identifier(ast->identifier_token);
|
||||||
@@ -2896,7 +2902,7 @@ bool Bind::visit(ClassSpecifierAST *ast)
|
|||||||
|
|
||||||
const Name *className = this->name(ast->name);
|
const Name *className = this->name(ast->name);
|
||||||
|
|
||||||
if (ast->name) {
|
if (ast->name && ! ast->name->asAnonymousName()) {
|
||||||
sourceLocation = location(ast->name, sourceLocation);
|
sourceLocation = location(ast->name, sourceLocation);
|
||||||
startScopeOffset = tokenAt(sourceLocation).end(); // at the end of the class name
|
startScopeOffset = tokenAt(sourceLocation).end(); // at the end of the class name
|
||||||
|
|
||||||
|
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -237,6 +237,7 @@ protected:
|
|||||||
virtual bool visit(QualifiedNameAST *ast);
|
virtual bool visit(QualifiedNameAST *ast);
|
||||||
virtual bool visit(OperatorFunctionIdAST *ast);
|
virtual bool visit(OperatorFunctionIdAST *ast);
|
||||||
virtual bool visit(ConversionFunctionIdAST *ast);
|
virtual bool visit(ConversionFunctionIdAST *ast);
|
||||||
|
virtual bool visit(AnonymousNameAST *ast);
|
||||||
virtual bool visit(SimpleNameAST *ast);
|
virtual bool visit(SimpleNameAST *ast);
|
||||||
virtual bool visit(DestructorNameAST *ast);
|
virtual bool visit(DestructorNameAST *ast);
|
||||||
virtual bool visit(TemplateIdAST *ast);
|
virtual bool visit(TemplateIdAST *ast);
|
||||||
|
@@ -73,6 +73,7 @@ class SymbolTable;
|
|||||||
class NameVisitor;
|
class NameVisitor;
|
||||||
class Name;
|
class Name;
|
||||||
class Identifier;
|
class Identifier;
|
||||||
|
class AnonymousNameId;
|
||||||
class TemplateNameId;
|
class TemplateNameId;
|
||||||
class DestructorNameId;
|
class DestructorNameId;
|
||||||
class OperatorNameId;
|
class OperatorNameId;
|
||||||
|
17
src/libs/3rdparty/cplusplus/Control.cpp
vendored
17
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -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>
|
template <> struct Compare<DestructorNameId>
|
||||||
{
|
{
|
||||||
bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const
|
bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const
|
||||||
@@ -219,6 +227,11 @@ public:
|
|||||||
delete_array_entries(symbols);
|
delete_array_entries(symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AnonymousNameId *findOrInsertAnonymousNameId(unsigned classTokenIndex)
|
||||||
|
{
|
||||||
|
return anonymousNameIds.intern(AnonymousNameId(classTokenIndex));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Iterator>
|
template <typename _Iterator>
|
||||||
const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, bool isSpecialization,
|
const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, bool isSpecialization,
|
||||||
_Iterator first, _Iterator last)
|
_Iterator first, _Iterator last)
|
||||||
@@ -475,6 +488,7 @@ public:
|
|||||||
// ### replace std::map with lookup tables. ASAP!
|
// ### replace std::map with lookup tables. ASAP!
|
||||||
|
|
||||||
// names
|
// names
|
||||||
|
Table<AnonymousNameId> anonymousNameIds;
|
||||||
Table<DestructorNameId> destructorNameIds;
|
Table<DestructorNameId> destructorNameIds;
|
||||||
Table<OperatorNameId> operatorNameIds;
|
Table<OperatorNameId> operatorNameIds;
|
||||||
Table<ConversionNameId> conversionNameIds;
|
Table<ConversionNameId> conversionNameIds;
|
||||||
@@ -550,6 +564,9 @@ DiagnosticClient *Control::diagnosticClient() const
|
|||||||
void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
|
void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
|
||||||
{ d->diagnosticClient = diagnosticClient; }
|
{ d->diagnosticClient = diagnosticClient; }
|
||||||
|
|
||||||
|
const AnonymousNameId *Control::anonymousNameId(unsigned classTokenIndex)
|
||||||
|
{ return d->findOrInsertAnonymousNameId(classTokenIndex); }
|
||||||
|
|
||||||
const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
|
const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
|
||||||
{
|
{
|
||||||
Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
|
Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
|
||||||
|
3
src/libs/3rdparty/cplusplus/Control.h
vendored
3
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -49,6 +49,9 @@ public:
|
|||||||
DiagnosticClient *diagnosticClient() const;
|
DiagnosticClient *diagnosticClient() const;
|
||||||
void setDiagnosticClient(DiagnosticClient *diagnosticClient);
|
void setDiagnosticClient(DiagnosticClient *diagnosticClient);
|
||||||
|
|
||||||
|
/// Returns the canonical anonymous name id
|
||||||
|
const AnonymousNameId *anonymousNameId(unsigned classTokenIndex);
|
||||||
|
|
||||||
/// Returns the canonical template name id.
|
/// Returns the canonical template name id.
|
||||||
const TemplateNameId *templateNameId(const Identifier *id,
|
const TemplateNameId *templateNameId(const Identifier *id,
|
||||||
bool isSpecialization,
|
bool isSpecialization,
|
||||||
|
3
src/libs/3rdparty/cplusplus/Name.cpp
vendored
3
src/libs/3rdparty/cplusplus/Name.cpp
vendored
@@ -36,6 +36,9 @@ Name::~Name()
|
|||||||
bool Name::isNameId() const
|
bool Name::isNameId() const
|
||||||
{ return asNameId() != 0; }
|
{ return asNameId() != 0; }
|
||||||
|
|
||||||
|
bool Name::isAnonymousNameId() const
|
||||||
|
{ return asAnonymousNameId() != 0; }
|
||||||
|
|
||||||
bool Name::isTemplateNameId() const
|
bool Name::isTemplateNameId() const
|
||||||
{ return asTemplateNameId() != 0; }
|
{ return asTemplateNameId() != 0; }
|
||||||
|
|
||||||
|
2
src/libs/3rdparty/cplusplus/Name.h
vendored
2
src/libs/3rdparty/cplusplus/Name.h
vendored
@@ -36,6 +36,7 @@ public:
|
|||||||
virtual const Identifier *identifier() const = 0;
|
virtual const Identifier *identifier() const = 0;
|
||||||
|
|
||||||
bool isNameId() const;
|
bool isNameId() const;
|
||||||
|
bool isAnonymousNameId() const;
|
||||||
bool isTemplateNameId() const;
|
bool isTemplateNameId() const;
|
||||||
bool isDestructorNameId() const;
|
bool isDestructorNameId() const;
|
||||||
bool isOperatorNameId() const;
|
bool isOperatorNameId() const;
|
||||||
@@ -44,6 +45,7 @@ public:
|
|||||||
bool isSelectorNameId() const;
|
bool isSelectorNameId() const;
|
||||||
|
|
||||||
virtual const Identifier *asNameId() const { return 0; }
|
virtual const Identifier *asNameId() const { return 0; }
|
||||||
|
virtual const AnonymousNameId *asAnonymousNameId() const { return 0; }
|
||||||
virtual const TemplateNameId *asTemplateNameId() const { return 0; }
|
virtual const TemplateNameId *asTemplateNameId() const { return 0; }
|
||||||
virtual const DestructorNameId *asDestructorNameId() const { return 0; }
|
virtual const DestructorNameId *asDestructorNameId() const { return 0; }
|
||||||
virtual const OperatorNameId *asOperatorNameId() const { return 0; }
|
virtual const OperatorNameId *asOperatorNameId() const { return 0; }
|
||||||
|
1
src/libs/3rdparty/cplusplus/NameVisitor.h
vendored
1
src/libs/3rdparty/cplusplus/NameVisitor.h
vendored
@@ -40,6 +40,7 @@ public:
|
|||||||
virtual bool preVisit(const Name *) { return true; }
|
virtual bool preVisit(const Name *) { return true; }
|
||||||
virtual void postVisit(const Name *) {}
|
virtual void postVisit(const Name *) {}
|
||||||
|
|
||||||
|
virtual void visit(const AnonymousNameId *) {}
|
||||||
virtual void visit(const Identifier *) {}
|
virtual void visit(const Identifier *) {}
|
||||||
virtual void visit(const TemplateNameId *) {}
|
virtual void visit(const TemplateNameId *) {}
|
||||||
virtual void visit(const DestructorNameId *) {}
|
virtual void visit(const DestructorNameId *) {}
|
||||||
|
26
src/libs/3rdparty/cplusplus/Names.cpp
vendored
26
src/libs/3rdparty/cplusplus/Names.cpp
vendored
@@ -249,3 +249,29 @@ bool SelectorNameId::isEqualTo(const Name *other) const
|
|||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
23
src/libs/3rdparty/cplusplus/Names.h
vendored
23
src/libs/3rdparty/cplusplus/Names.h
vendored
@@ -253,6 +253,29 @@ private:
|
|||||||
bool _hasArguments;
|
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
|
} // namespace CPlusPlus
|
||||||
|
|
||||||
#endif // CPLUSPLUS_NAMES_H
|
#endif // CPLUSPLUS_NAMES_H
|
||||||
|
6
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
6
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -2003,6 +2003,12 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node)
|
|||||||
NameAST *name = 0;
|
NameAST *name = 0;
|
||||||
parseName(name);
|
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;
|
bool parsed = false;
|
||||||
|
|
||||||
const bool previousInFunctionBody = _inFunctionBody;
|
const bool previousInFunctionBody = _inFunctionBody;
|
||||||
|
@@ -60,7 +60,7 @@ static void addNames(const Name *name, QList<const Name *> *names, bool addAllNa
|
|||||||
else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
||||||
addNames(q->base(), names);
|
addNames(q->base(), names);
|
||||||
addNames(q->name(), names, addAllNames);
|
addNames(q->name(), names, addAllNames);
|
||||||
} else if (addAllNames || name->isNameId() || name->isTemplateNameId()) {
|
} else if (addAllNames || name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||||
names->append(name);
|
names->append(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -716,7 +716,7 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
|
|||||||
} else if (! processed->contains(this)) {
|
} else if (! processed->contains(this)) {
|
||||||
processed->insert(this);
|
processed->insert(this);
|
||||||
|
|
||||||
if (name->isNameId() || name->isTemplateNameId()) {
|
if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
foreach (Symbol *s, symbols()) {
|
foreach (Symbol *s, symbols()) {
|
||||||
@@ -798,10 +798,26 @@ ClassOrNamespace *ClassOrNamespace::findSpecializationWithPointer(const Template
|
|||||||
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
|
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
|
||||||
{
|
{
|
||||||
Q_ASSERT(name != 0);
|
Q_ASSERT(name != 0);
|
||||||
Q_ASSERT(name->isNameId() || name->isTemplateNameId());
|
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
|
||||||
|
|
||||||
const_cast<ClassOrNamespace *>(this)->flush();
|
const_cast<ClassOrNamespace *>(this)->flush();
|
||||||
|
|
||||||
|
const AnonymousNameId *anonymousNameId = name->asAnonymousNameId();
|
||||||
|
if (anonymousNameId) {
|
||||||
|
QHash<const AnonymousNameId *, ClassOrNamespace *>::const_iterator cit
|
||||||
|
= _anonymouses.find(anonymousNameId);
|
||||||
|
if (cit != _anonymouses.end()) {
|
||||||
|
return cit.value();
|
||||||
|
} else {
|
||||||
|
ClassOrNamespace *newAnonymous = _factory->allocClassOrNamespace(this);
|
||||||
|
#ifdef DEBUG_LOOKUP
|
||||||
|
newAnonymous->_name = anonymousNameId;
|
||||||
|
#endif // DEBUG_LOOKUP
|
||||||
|
_anonymouses[anonymousNameId] = newAnonymous;
|
||||||
|
return newAnonymous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Table::const_iterator it = _classOrNamespaces.find(name);
|
Table::const_iterator it = _classOrNamespaces.find(name);
|
||||||
if (it == _classOrNamespaces.end())
|
if (it == _classOrNamespaces.end())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1201,7 +1217,7 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
|
|||||||
|
|
||||||
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin);
|
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin);
|
||||||
|
|
||||||
} else if (name->isNameId() || name->isTemplateNameId()) {
|
} else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||||
ClassOrNamespace *e = nestedType(name, origin);
|
ClassOrNamespace *e = nestedType(name, origin);
|
||||||
|
|
||||||
if (! e) {
|
if (! e) {
|
||||||
@@ -1470,7 +1486,7 @@ bool CreateBindings::visit(NamespaceAlias *a)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
|
} else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
|
||||||
if (a->name()->isNameId() || a->name()->isTemplateNameId())
|
if (a->name()->isNameId() || a->name()->isTemplateNameId() || a->name()->isAnonymousNameId())
|
||||||
_currentClassOrNamespace->addNestedType(a->name(), e);
|
_currentClassOrNamespace->addNestedType(a->name(), e);
|
||||||
|
|
||||||
} else if (false) {
|
} else if (false) {
|
||||||
|
@@ -131,6 +131,7 @@ private:
|
|||||||
QSharedPointer<Control> _control;
|
QSharedPointer<Control> _control;
|
||||||
TemplateNameIdTable _specializations;
|
TemplateNameIdTable _specializations;
|
||||||
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
|
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
|
||||||
|
QHash<const AnonymousNameId *, ClassOrNamespace *> _anonymouses;
|
||||||
|
|
||||||
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
|
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
|
||||||
|
|
||||||
|
@@ -268,3 +268,8 @@ void NamePrettyPrinter::visit(const SelectorNameId *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NamePrettyPrinter::visit(const AnonymousNameId *name)
|
||||||
|
{
|
||||||
|
_name = QString(QLatin1String("Anonymous:%1")).arg(name->classTokenIndex());
|
||||||
|
}
|
||||||
|
@@ -57,6 +57,7 @@ protected:
|
|||||||
virtual void visit(const ConversionNameId *name);
|
virtual void visit(const ConversionNameId *name);
|
||||||
virtual void visit(const QualifiedNameId *name);
|
virtual void visit(const QualifiedNameId *name);
|
||||||
virtual void visit(const SelectorNameId *name);
|
virtual void visit(const SelectorNameId *name);
|
||||||
|
virtual void visit(const AnonymousNameId *name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Overview *_overview;
|
const Overview *_overview;
|
||||||
|
@@ -188,6 +188,9 @@ private slots:
|
|||||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||||
void test_checksymbols_templated_functions();
|
void test_checksymbols_templated_functions();
|
||||||
void test_checksymbols_QTCREATORBUG9098();
|
void test_checksymbols_QTCREATORBUG9098();
|
||||||
|
void test_checksymbols_AnonymousClass();
|
||||||
|
void test_checksymbols_AnonymousClass_insideNamespace();
|
||||||
|
void test_checksymbols_AnonymousClass_QTCREATORBUG8963();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
||||||
@@ -1421,6 +1424,28 @@ void tst_CheckSymbols::test_checksymbols_templated_functions()
|
|||||||
TestData::check(source, expectedUses);
|
TestData::check(source, expectedUses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_AnonymousClass()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"struct\n"
|
||||||
|
"{\n"
|
||||||
|
" int foo;\n"
|
||||||
|
"} Foo;\n"
|
||||||
|
"\n"
|
||||||
|
"void fun()\n"
|
||||||
|
"{\n"
|
||||||
|
" foo = 3;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(3, 7, 3, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(6, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
||||||
{
|
{
|
||||||
const QByteArray source =
|
const QByteArray source =
|
||||||
@@ -1460,5 +1485,87 @@ void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
|||||||
TestData::check(source, expectedUses);
|
TestData::check(source, expectedUses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_AnonymousClass_insideNamespace()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"struct { int foo1; } Foo1;\n"
|
||||||
|
"void bar1()\n"
|
||||||
|
"{\n"
|
||||||
|
" Foo1.foo1 = 42;\n"
|
||||||
|
"}\n"
|
||||||
|
"namespace Ns1 {\n"
|
||||||
|
" struct { int foo2; } Foo2;\n"
|
||||||
|
" void bar2()\n"
|
||||||
|
" {\n"
|
||||||
|
" Foo2.foo2 = 42;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
"namespace Ns2 {\n"
|
||||||
|
" struct {\n"
|
||||||
|
" struct { struct { int foo3; }; };\n"
|
||||||
|
" void func() { foo3 = 42; }\n"
|
||||||
|
" } Foo3;\n"
|
||||||
|
" void bar3()\n"
|
||||||
|
" {\n"
|
||||||
|
" Foo3.foo3 = 42;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(1, 14, 4, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(2, 6, 4, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(4, 8, 4, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(6, 11, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(7, 16, 4, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(8, 8, 4, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(10, 10, 4, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(13, 11, 3, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(15, 27, 4, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(16, 10, 4, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(18, 8, 4, CppHighlightingSupport::FunctionUse)
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_AnonymousClass_QTCREATORBUG8963()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"typedef enum {\n"
|
||||||
|
" FIRST\n"
|
||||||
|
"} isNotInt;\n"
|
||||||
|
"typedef struct {\n"
|
||||||
|
" int isint;\n"
|
||||||
|
" int isNotInt;\n"
|
||||||
|
"} Struct;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" Struct s;\n"
|
||||||
|
" s.isint;\n"
|
||||||
|
" s.isNotInt;\n"
|
||||||
|
" FIRST;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(2, 5, 5, CppHighlightingSupport::EnumerationUse)
|
||||||
|
<< Use(3, 3, 8, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(5, 9, 5, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(6, 9, 8, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(7, 3, 6, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(8, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||||
|
<< Use(10, 5, 6, CppHighlightingSupport::TypeUse)
|
||||||
|
<< Use(10, 12, 1, CppHighlightingSupport::LocalUse)
|
||||||
|
<< Use(11, 5, 1, CppHighlightingSupport::LocalUse)
|
||||||
|
<< Use(11, 7, 5, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(12, 5, 1, CppHighlightingSupport::LocalUse)
|
||||||
|
<< Use(12, 7, 8, CppHighlightingSupport::FieldUse)
|
||||||
|
<< Use(13, 5, 5, CppHighlightingSupport::EnumerationUse)
|
||||||
|
;
|
||||||
|
|
||||||
|
TestData::check(source, expectedUses);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
||||||
#include "tst_checksymbols.moc"
|
#include "tst_checksymbols.moc"
|
||||||
|
@@ -96,6 +96,8 @@ private Q_SLOTS:
|
|||||||
void instantiateTemplateWithNestedClass();
|
void instantiateTemplateWithNestedClass();
|
||||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||||
void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005();
|
void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005();
|
||||||
|
void anonymousClass_QTCREATORBUG8963();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_FindUsages::inlineMethod()
|
void tst_FindUsages::inlineMethod()
|
||||||
@@ -475,7 +477,6 @@ void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG90
|
|||||||
|
|
||||||
QVERIFY(doc->diagnosticMessages().isEmpty());
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
QCOMPARE(doc->globalSymbolCount(), 3U);
|
QCOMPARE(doc->globalSymbolCount(), 3U);
|
||||||
|
|
||||||
Snapshot snapshot;
|
Snapshot snapshot;
|
||||||
snapshot.insert(doc);
|
snapshot.insert(doc);
|
||||||
|
|
||||||
@@ -488,6 +489,50 @@ void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG90
|
|||||||
|
|
||||||
FindUsages findUsages(src, doc, snapshot);
|
FindUsages findUsages(src, doc, snapshot);
|
||||||
findUsages(fooDeclaration);
|
findUsages(fooDeclaration);
|
||||||
|
|
||||||
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::anonymousClass_QTCREATORBUG8963()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
"typedef enum {\n"
|
||||||
|
" FIRST\n"
|
||||||
|
"} isNotInt;\n"
|
||||||
|
"typedef struct {\n"
|
||||||
|
" int isint;\n"
|
||||||
|
" int isNotInt;\n"
|
||||||
|
"} Struct;\n"
|
||||||
|
"void foo()\n"
|
||||||
|
"{\n"
|
||||||
|
" Struct s;\n"
|
||||||
|
" s.isint;\n"
|
||||||
|
" s.isNotInt;\n"
|
||||||
|
" FIRST;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("anonymousClass_QTCREATORBUG8963");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QCOMPARE(doc->globalSymbolCount(), 5U);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Class *structSymbol = doc->globalSymbolAt(2)->asClass();
|
||||||
|
QVERIFY(structSymbol);
|
||||||
|
QCOMPARE(structSymbol->memberCount(), 2U);
|
||||||
|
Declaration *isNotIntDeclaration = structSymbol->memberAt(1)->asDeclaration();
|
||||||
|
QVERIFY(isNotIntDeclaration);
|
||||||
|
QCOMPARE(isNotIntDeclaration->name()->identifier()->chars(), "isNotInt");
|
||||||
|
|
||||||
|
FindUsages findUsages(src, doc, snapshot);
|
||||||
|
findUsages(isNotIntDeclaration);
|
||||||
|
|
||||||
QCOMPARE(findUsages.usages().size(), 2);
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -796,6 +796,13 @@ virtual bool visit(ConversionFunctionIdAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool visit(AnonymousNameAST *ast)
|
||||||
|
{
|
||||||
|
if (ast->class_token)
|
||||||
|
terminal(ast->class_token, ast);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool visit(SimpleNameAST *ast)
|
virtual bool visit(SimpleNameAST *ast)
|
||||||
{
|
{
|
||||||
if (ast->identifier_token)
|
if (ast->identifier_token)
|
||||||
|
Reference in New Issue
Block a user