forked from qt-creator/qt-creator
C++: Revert lookup to 3.4.2
...which was least buggy. The bugs fixed by the changes we revert here (highlighting/completion for code involving templates) were minor compared to ones we currently have. Those bugs will be addressed by the clang code model anyway. Relevant commits were collected via: $ cd ${QTC}/src/libs/cplusplus $ git log \ --no-merges \ --format=oneline \ v3.4.2..HEAD \ -- LookupContext.* ResolveExpression.* TypeResolver.* TypeOfExpression.* \ ../../plugins/cpptools/cppcompletion_test.cpp From this list the following were skipped due to irrelevance:88c5b47e53
# CppTools: Minor cleanup in completion testse5255a1f5c
# CppTools: Add a test for ObjC not replacing dot with arrow5b12c8d63a
# CppTools: Support ObjC in member access operator tests9fef4fb9ca
# CPlusPlus: Fix warnings about overriding visit(...) methods There were only minor conflicts while reverting those. This changes touches so many files because there were quite some cleanups and renames after the 3.4.2 release. Task-number: QTCREATORBUG-14889 Task-number: QTCREATORBUG-15211 Task-number: QTCREATORBUG-15213 Task-number: QTCREATORBUG-15257 Task-number: QTCREATORBUG-15264 Task-number: QTCREATORBUG-15291 Task-number: QTCREATORBUG-15329 Change-Id: I01f759f8f35ecb4228928a4f22086e279c1a5435 Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
2
src/libs/3rdparty/cplusplus/AST.h
vendored
2
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -3349,7 +3349,7 @@ public:
|
||||
DeclarationAST *declaration;
|
||||
|
||||
public: // annotations
|
||||
Scope *symbol;
|
||||
Template *symbol;
|
||||
|
||||
public:
|
||||
TemplateDeclarationAST()
|
||||
|
40
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
40
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -1917,19 +1917,9 @@ bool Bind::visit(SimpleDeclarationAST *ast)
|
||||
methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
|
||||
|
||||
// unsigned qt_invokable_token = ast->qt_invokable_token;
|
||||
const ExpressionAST *declTypeExpression = 0;
|
||||
bool isTypedef = false;
|
||||
FullySpecifiedType type;
|
||||
for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
|
||||
type = this->specifier(it->value, type);
|
||||
if (type.isTypedef())
|
||||
isTypedef = true;
|
||||
|
||||
type.setTypedef(isTypedef);
|
||||
if (type.isDecltype()) {
|
||||
if (DecltypeSpecifierAST *decltypeSpec = it->value->asDecltypeSpecifier())
|
||||
declTypeExpression = decltypeSpec->expression;
|
||||
}
|
||||
}
|
||||
|
||||
List<Symbol *> **symbolTail = &ast->symbols;
|
||||
@@ -1985,8 +1975,6 @@ bool Bind::visit(SimpleDeclarationAST *ast)
|
||||
translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer");
|
||||
else if (initializer)
|
||||
decl->setInitializer(asStringLiteral(initializer));
|
||||
} else if (declTy.isDecltype()) {
|
||||
decl->setInitializer(asStringLiteral(declTypeExpression));
|
||||
}
|
||||
|
||||
if (_scope->isClass()) {
|
||||
@@ -2367,15 +2355,11 @@ bool Bind::visit(ParameterDeclarationAST *ast)
|
||||
|
||||
bool Bind::visit(TemplateDeclarationAST *ast)
|
||||
{
|
||||
Scope *scope = 0;
|
||||
if (ast->less_token)
|
||||
scope = control()->newTemplate(ast->firstToken(), 0);
|
||||
else
|
||||
scope = control()->newExplicitInstantiation(ast->firstToken(), 0);
|
||||
scope->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
|
||||
scope->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
|
||||
ast->symbol = scope;
|
||||
Scope *previousScope = switchScope(scope);
|
||||
Template *templ = control()->newTemplate(ast->firstToken(), 0);
|
||||
templ->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
|
||||
templ->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
|
||||
ast->symbol = templ;
|
||||
Scope *previousScope = switchScope(templ);
|
||||
|
||||
for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) {
|
||||
this->declaration(it->value);
|
||||
@@ -2384,17 +2368,12 @@ bool Bind::visit(TemplateDeclarationAST *ast)
|
||||
this->declaration(ast->declaration);
|
||||
(void) switchScope(previousScope);
|
||||
|
||||
Symbol *decl = 0;
|
||||
if (Template *templ = scope->asTemplate())
|
||||
decl = templ->declaration();
|
||||
else if (ExplicitInstantiation *inst = scope->asExplicitInstantiation())
|
||||
decl = inst->declaration();
|
||||
if (decl) {
|
||||
scope->setSourceLocation(decl->sourceLocation(), translationUnit());
|
||||
scope->setName(decl->name());
|
||||
if (Symbol *decl = templ->declaration()) {
|
||||
templ->setSourceLocation(decl->sourceLocation(), translationUnit());
|
||||
templ->setName(decl->name());
|
||||
}
|
||||
|
||||
_scope->addMember(scope);
|
||||
_scope->addMember(templ);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3039,7 +3018,6 @@ bool Bind::visit(TypeofSpecifierAST *ast)
|
||||
bool Bind::visit(DecltypeSpecifierAST *ast)
|
||||
{
|
||||
_type = this->expression(ast->expression);
|
||||
_type.setDecltype(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -112,7 +112,6 @@ class Function;
|
||||
class Namespace;
|
||||
class NamespaceAlias;
|
||||
class Template;
|
||||
class ExplicitInstantiation;
|
||||
class BaseClass;
|
||||
class Block;
|
||||
class Class;
|
||||
|
16
src/libs/3rdparty/cplusplus/Control.cpp
vendored
16
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -366,16 +366,9 @@ public:
|
||||
|
||||
Template *newTemplate(unsigned sourceLocation, const Name *name)
|
||||
{
|
||||
Template *templ = new Template(translationUnit, sourceLocation, name);
|
||||
symbols.push_back(templ);
|
||||
return templ;
|
||||
}
|
||||
|
||||
ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name)
|
||||
{
|
||||
ExplicitInstantiation *inst = new ExplicitInstantiation(translationUnit, sourceLocation, name);
|
||||
symbols.push_back(inst);
|
||||
return inst;
|
||||
Template *ns = new Template(translationUnit, sourceLocation, name);
|
||||
symbols.push_back(ns);
|
||||
return ns;
|
||||
}
|
||||
|
||||
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name)
|
||||
@@ -699,9 +692,6 @@ Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name)
|
||||
Template *Control::newTemplate(unsigned sourceLocation, const Name *name)
|
||||
{ return d->newTemplate(sourceLocation, name); }
|
||||
|
||||
ExplicitInstantiation *Control::newExplicitInstantiation(unsigned sourceLocation, const Name *name)
|
||||
{ return d->newExplicitInstantiation(sourceLocation, name); }
|
||||
|
||||
NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name)
|
||||
{ return d->newNamespaceAlias(sourceLocation, name); }
|
||||
|
||||
|
3
src/libs/3rdparty/cplusplus/Control.h
vendored
3
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -120,9 +120,6 @@ public:
|
||||
/// Creates a new Template symbol.
|
||||
Template *newTemplate(unsigned sourceLocation, const Name *name = 0);
|
||||
|
||||
/// Creates a new ExplicitInstantiation symbol.
|
||||
ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name = 0);
|
||||
|
||||
/// Creates a new Namespace symbol.
|
||||
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0);
|
||||
|
||||
|
@@ -100,12 +100,6 @@ bool FullySpecifiedType::isAuto() const
|
||||
void FullySpecifiedType::setAuto(bool isAuto)
|
||||
{ f._isAuto = isAuto; }
|
||||
|
||||
bool FullySpecifiedType::isDecltype() const
|
||||
{ return f._isDecltype; }
|
||||
|
||||
void FullySpecifiedType::setDecltype(bool isDecltype)
|
||||
{ f._isDecltype = isDecltype; }
|
||||
|
||||
bool FullySpecifiedType::isRegister() const
|
||||
{ return f._isRegister; }
|
||||
|
||||
|
@@ -58,9 +58,6 @@ public:
|
||||
bool isAuto() const;
|
||||
void setAuto(bool isAuto);
|
||||
|
||||
bool isDecltype() const;
|
||||
void setDecltype(bool isDecltype);
|
||||
|
||||
bool isRegister() const;
|
||||
void setRegister(bool isRegister);
|
||||
|
||||
@@ -128,7 +125,6 @@ private:
|
||||
// storage class specifiers
|
||||
unsigned _isFriend: 1;
|
||||
unsigned _isAuto: 1;
|
||||
unsigned _isDecltype: 1;
|
||||
unsigned _isRegister: 1;
|
||||
unsigned _isStatic: 1;
|
||||
unsigned _isExtern: 1;
|
||||
|
11
src/libs/3rdparty/cplusplus/Matcher.cpp
vendored
11
src/libs/3rdparty/cplusplus/Matcher.cpp
vendored
@@ -218,17 +218,6 @@ bool Matcher::match(const Template *type, const Template *otherType)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matcher::match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType)
|
||||
{
|
||||
if (type == otherType)
|
||||
return true;
|
||||
|
||||
if (! Matcher::match(type->name(), otherType->name(), this))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType)
|
||||
{
|
||||
if (type == otherType)
|
||||
|
1
src/libs/3rdparty/cplusplus/Matcher.h
vendored
1
src/libs/3rdparty/cplusplus/Matcher.h
vendored
@@ -61,7 +61,6 @@ public:
|
||||
virtual bool match(const Enum *type, const Enum *otherType);
|
||||
virtual bool match(const Namespace *type, const Namespace *otherType);
|
||||
virtual bool match(const Template *type, const Template *otherType);
|
||||
virtual bool match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType);
|
||||
virtual bool match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType);
|
||||
virtual bool match(const Class *type, const Class *otherType);
|
||||
virtual bool match(const ObjCClass *type, const ObjCClass *otherType);
|
||||
|
2
src/libs/3rdparty/cplusplus/Names.h
vendored
2
src/libs/3rdparty/cplusplus/Names.h
vendored
@@ -100,7 +100,7 @@ public:
|
||||
TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
|
||||
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
|
||||
bool isSpecialization() const { return _isSpecialization; }
|
||||
// this is temporary solution needed in LookupScope::nestedType
|
||||
// this is temporary solution needed in ClassOrNamespace::nestedType
|
||||
// when we try to find correct specialization for instantiation
|
||||
void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; }
|
||||
|
||||
|
2
src/libs/3rdparty/cplusplus/Scope.cpp
vendored
2
src/libs/3rdparty/cplusplus/Scope.cpp
vendored
@@ -215,7 +215,7 @@ unsigned SymbolTable::symbolCount() const
|
||||
|
||||
Symbol *SymbolTable::symbolAt(unsigned index) const
|
||||
{
|
||||
if (! _symbols || index >= symbolCount())
|
||||
if (! _symbols)
|
||||
return 0;
|
||||
return _symbols[index];
|
||||
}
|
||||
|
3
src/libs/3rdparty/cplusplus/Symbol.cpp
vendored
3
src/libs/3rdparty/cplusplus/Symbol.cpp
vendored
@@ -361,9 +361,6 @@ bool Symbol::isNamespace() const
|
||||
bool Symbol::isTemplate() const
|
||||
{ return asTemplate() != 0; }
|
||||
|
||||
bool Symbol::isExplicitInstantiation() const
|
||||
{ return asExplicitInstantiation() != 0; }
|
||||
|
||||
bool Symbol::isClass() const
|
||||
{ return asClass() != 0; }
|
||||
|
||||
|
7
src/libs/3rdparty/cplusplus/Symbol.h
vendored
7
src/libs/3rdparty/cplusplus/Symbol.h
vendored
@@ -135,7 +135,7 @@ public:
|
||||
/// Returns true if this Symbol is an Enum.
|
||||
bool isEnum() const;
|
||||
|
||||
/// Returns true if this Symbol is a Function.
|
||||
/// Returns true if this Symbol is an Function.
|
||||
bool isFunction() const;
|
||||
|
||||
/// Returns true if this Symbol is a Namespace.
|
||||
@@ -144,9 +144,6 @@ public:
|
||||
/// Returns true if this Symbol is a Template.
|
||||
bool isTemplate() const;
|
||||
|
||||
/// Returns true if this Symbol is an ExplicitInstantiation.
|
||||
bool isExplicitInstantiation() const;
|
||||
|
||||
/// Returns true if this Symbol is a Class.
|
||||
bool isClass() const;
|
||||
|
||||
@@ -206,7 +203,6 @@ public:
|
||||
virtual const Function *asFunction() const { return 0; }
|
||||
virtual const Namespace *asNamespace() const { return 0; }
|
||||
virtual const Template *asTemplate() const { return 0; }
|
||||
virtual const ExplicitInstantiation *asExplicitInstantiation() const { return 0; }
|
||||
virtual const NamespaceAlias *asNamespaceAlias() const { return 0; }
|
||||
virtual const Class *asClass() const { return 0; }
|
||||
virtual const Block *asBlock() const { return 0; }
|
||||
@@ -233,7 +229,6 @@ public:
|
||||
virtual Function *asFunction() { return 0; }
|
||||
virtual Namespace *asNamespace() { return 0; }
|
||||
virtual Template *asTemplate() { return 0; }
|
||||
virtual ExplicitInstantiation *asExplicitInstantiation() { return 0; }
|
||||
virtual NamespaceAlias *asNamespaceAlias() { return 0; }
|
||||
virtual Class *asClass() { return 0; }
|
||||
virtual Block *asBlock() { return 0; }
|
||||
|
1
src/libs/3rdparty/cplusplus/SymbolVisitor.h
vendored
1
src/libs/3rdparty/cplusplus/SymbolVisitor.h
vendored
@@ -51,7 +51,6 @@ public:
|
||||
virtual bool visit(Function *) { return true; }
|
||||
virtual bool visit(Namespace *) { return true; }
|
||||
virtual bool visit(Template *) { return true; }
|
||||
virtual bool visit(ExplicitInstantiation *) { return true; }
|
||||
virtual bool visit(Class *) { return true; }
|
||||
virtual bool visit(Block *) { return true; }
|
||||
virtual bool visit(ForwardClassDeclaration *) { return true; }
|
||||
|
52
src/libs/3rdparty/cplusplus/Symbols.cpp
vendored
52
src/libs/3rdparty/cplusplus/Symbols.cpp
vendored
@@ -481,12 +481,10 @@ void Enum::visitSymbol0(SymbolVisitor *visitor)
|
||||
|
||||
Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
|
||||
: Scope(translationUnit, sourceLocation, name)
|
||||
, _isExplicitInstantiation(false)
|
||||
{ }
|
||||
|
||||
Template::Template(Clone *clone, Subst *subst, Template *original)
|
||||
: Scope(clone, subst, original)
|
||||
, _isExplicitInstantiation(original->_isExplicitInstantiation)
|
||||
{ }
|
||||
|
||||
Template::~Template()
|
||||
@@ -539,56 +537,6 @@ bool Template::match0(const Type *otherType, Matcher *matcher) const
|
||||
return false;
|
||||
}
|
||||
|
||||
ExplicitInstantiation::ExplicitInstantiation(TranslationUnit *translationUnit,
|
||||
unsigned sourceLocation, const Name *name)
|
||||
: Scope(translationUnit, sourceLocation, name)
|
||||
{ }
|
||||
|
||||
ExplicitInstantiation::ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original)
|
||||
: Scope(clone, subst, original)
|
||||
{ }
|
||||
|
||||
ExplicitInstantiation::~ExplicitInstantiation()
|
||||
{ }
|
||||
|
||||
Symbol *ExplicitInstantiation::declaration() const
|
||||
{
|
||||
if (isEmpty())
|
||||
return 0;
|
||||
|
||||
if (Symbol *s = memberAt(memberCount() - 1)) {
|
||||
if (s->isClass() || s->isForwardClassDeclaration() ||
|
||||
s->isTemplate() || s->isExplicitInstantiation() ||
|
||||
s->isFunction() || s->isDeclaration()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FullySpecifiedType ExplicitInstantiation::type() const
|
||||
{ return FullySpecifiedType(const_cast<ExplicitInstantiation *>(this)); }
|
||||
|
||||
void ExplicitInstantiation::visitSymbol0(SymbolVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
for (unsigned i = 0; i < memberCount(); ++i) {
|
||||
visitSymbol(memberAt(i), visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExplicitInstantiation::accept0(TypeVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
bool ExplicitInstantiation::match0(const Type *otherType, Matcher *matcher) const
|
||||
{
|
||||
if (const ExplicitInstantiation *otherTy = otherType->asExplicitInstantiationType())
|
||||
return matcher->match(this, otherTy);
|
||||
return false;
|
||||
}
|
||||
|
||||
Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
|
||||
: Scope(translationUnit, sourceLocation, name)
|
||||
, _isInline(false)
|
||||
|
33
src/libs/3rdparty/cplusplus/Symbols.h
vendored
33
src/libs/3rdparty/cplusplus/Symbols.h
vendored
@@ -423,41 +423,8 @@ protected:
|
||||
virtual void visitSymbol0(SymbolVisitor *visitor);
|
||||
virtual void accept0(TypeVisitor *visitor);
|
||||
virtual bool match0(const Type *otherType, Matcher *matcher) const;
|
||||
|
||||
private:
|
||||
bool _isExplicitInstantiation;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ExplicitInstantiation : public Scope, public Type
|
||||
{
|
||||
public:
|
||||
ExplicitInstantiation(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
|
||||
ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original);
|
||||
virtual ~ExplicitInstantiation();
|
||||
|
||||
Symbol *declaration() const;
|
||||
|
||||
// Symbol's interface
|
||||
virtual FullySpecifiedType type() const;
|
||||
|
||||
virtual const ExplicitInstantiation *asExplicitInstantiation() const
|
||||
{ return this; }
|
||||
|
||||
virtual ExplicitInstantiation *asExplicitInstantiation()
|
||||
{ return this; }
|
||||
|
||||
// Type's interface
|
||||
virtual const ExplicitInstantiation *asExplicitInstantiationType() const
|
||||
{ return this; }
|
||||
|
||||
virtual ExplicitInstantiation *asExplicitInstantiationType()
|
||||
{ return this; }
|
||||
|
||||
protected:
|
||||
virtual void visitSymbol0(SymbolVisitor *visitor);
|
||||
virtual void accept0(TypeVisitor *visitor);
|
||||
virtual bool match0(const Type *otherType, Matcher *matcher) const;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
|
||||
{
|
||||
|
18
src/libs/3rdparty/cplusplus/Templates.cpp
vendored
18
src/libs/3rdparty/cplusplus/Templates.cpp
vendored
@@ -125,12 +125,6 @@ void CloneType::visit(Template *type)
|
||||
_type = templ;
|
||||
}
|
||||
|
||||
void CloneType::visit(ExplicitInstantiation *type)
|
||||
{
|
||||
ExplicitInstantiation *inst = _clone->symbol(type, _subst)->asExplicitInstantiation();
|
||||
_type = inst;
|
||||
}
|
||||
|
||||
void CloneType::visit(Class *type)
|
||||
{
|
||||
Class *klass = _clone->symbol(type, _subst)->asClass();
|
||||
@@ -194,8 +188,10 @@ Symbol *CloneSymbol::cloneSymbol(Symbol *symbol, Subst *subst)
|
||||
|
||||
SymbolSubstPair symbolSubstPair = std::make_pair(symbol, subst);
|
||||
auto it = _cache.find(symbolSubstPair);
|
||||
if (it != _cache.end())
|
||||
if (it != _cache.end()) {
|
||||
if (it->second->enclosingScope() == symbol->enclosingScope())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Symbol *r = 0;
|
||||
std::swap(_subst, subst);
|
||||
@@ -297,14 +293,6 @@ bool CloneSymbol::visit(Template *symbol)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CloneSymbol::visit(ExplicitInstantiation *symbol)
|
||||
{
|
||||
ExplicitInstantiation *inst = new ExplicitInstantiation(_clone, _subst, symbol);
|
||||
_symbol = inst;
|
||||
_control->addSymbol(inst);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CloneSymbol::visit(Class *symbol)
|
||||
{
|
||||
Class *klass = new Class(_clone, _subst, symbol);
|
||||
|
2
src/libs/3rdparty/cplusplus/Templates.h
vendored
2
src/libs/3rdparty/cplusplus/Templates.h
vendored
@@ -85,7 +85,6 @@ protected:
|
||||
virtual void visit(Function *type);
|
||||
virtual void visit(Namespace *type);
|
||||
virtual void visit(Template *type);
|
||||
virtual void visit(ExplicitInstantiation *type);
|
||||
virtual void visit(Class *type);
|
||||
virtual void visit(Enum *type);
|
||||
virtual void visit(ForwardClassDeclaration *type);
|
||||
@@ -153,7 +152,6 @@ protected:
|
||||
virtual bool visit(Function *symbol);
|
||||
virtual bool visit(Namespace *symbol);
|
||||
virtual bool visit(Template *symbol);
|
||||
virtual bool visit(ExplicitInstantiation *symbol);
|
||||
virtual bool visit(Class *symbol);
|
||||
virtual bool visit(Block *symbol);
|
||||
virtual bool visit(ForwardClassDeclaration *symbol);
|
||||
|
3
src/libs/3rdparty/cplusplus/Type.cpp
vendored
3
src/libs/3rdparty/cplusplus/Type.cpp
vendored
@@ -68,9 +68,6 @@ bool Type::isNamespaceType() const
|
||||
bool Type::isTemplateType() const
|
||||
{ return asTemplateType() != 0; }
|
||||
|
||||
bool Type::isExplicitInstantiationType() const
|
||||
{ return asExplicitInstantiationType() != 0; }
|
||||
|
||||
bool Type::isClassType() const
|
||||
{ return asClassType() != 0; }
|
||||
|
||||
|
3
src/libs/3rdparty/cplusplus/Type.h
vendored
3
src/libs/3rdparty/cplusplus/Type.h
vendored
@@ -43,7 +43,6 @@ public:
|
||||
bool isFunctionType() const;
|
||||
bool isNamespaceType() const;
|
||||
bool isTemplateType() const;
|
||||
bool isExplicitInstantiationType() const;
|
||||
bool isClassType() const;
|
||||
bool isEnumType() const;
|
||||
bool isForwardClassDeclarationType() const;
|
||||
@@ -65,7 +64,6 @@ public:
|
||||
virtual const Function *asFunctionType() const { return 0; }
|
||||
virtual const Namespace *asNamespaceType() const { return 0; }
|
||||
virtual const Template *asTemplateType() const { return 0; }
|
||||
virtual const ExplicitInstantiation *asExplicitInstantiationType() const { return 0; }
|
||||
virtual const Class *asClassType() const { return 0; }
|
||||
virtual const Enum *asEnumType() const { return 0; }
|
||||
virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
|
||||
@@ -87,7 +85,6 @@ public:
|
||||
virtual Function *asFunctionType() { return 0; }
|
||||
virtual Namespace *asNamespaceType() { return 0; }
|
||||
virtual Template *asTemplateType() { return 0; }
|
||||
virtual ExplicitInstantiation *asExplicitInstantiationType() { return 0; }
|
||||
virtual Class *asClassType() { return 0; }
|
||||
virtual Enum *asEnumType() { return 0; }
|
||||
virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
|
||||
|
1
src/libs/3rdparty/cplusplus/TypeVisitor.h
vendored
1
src/libs/3rdparty/cplusplus/TypeVisitor.h
vendored
@@ -51,7 +51,6 @@ public:
|
||||
virtual void visit(Function *) {}
|
||||
virtual void visit(Namespace *) {}
|
||||
virtual void visit(Template *) {}
|
||||
virtual void visit(ExplicitInstantiation *) {}
|
||||
virtual void visit(Class *) {}
|
||||
virtual void visit(Enum *) {}
|
||||
virtual void visit(ForwardClassDeclaration *) {}
|
||||
|
@@ -379,7 +379,7 @@ FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
|
||||
}
|
||||
|
||||
|
||||
UseMinimalNames::UseMinimalNames(LookupScope *target)
|
||||
UseMinimalNames::UseMinimalNames(ClassOrNamespace *target)
|
||||
: _target(target)
|
||||
{
|
||||
|
||||
|
@@ -89,13 +89,13 @@ private:
|
||||
class CPLUSPLUS_EXPORT UseMinimalNames: public Substitution
|
||||
{
|
||||
public:
|
||||
UseMinimalNames(LookupScope *target);
|
||||
UseMinimalNames(ClassOrNamespace *target);
|
||||
virtual ~UseMinimalNames();
|
||||
|
||||
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
|
||||
|
||||
private:
|
||||
LookupScope *_target;
|
||||
ClassOrNamespace *_target;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT UseQualifiedNames: public UseMinimalNames
|
||||
|
430
src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
Normal file
430
src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "DeprecatedGenTemplateInstance.h"
|
||||
#include "Overview.h"
|
||||
|
||||
#include <cplusplus/Control.h>
|
||||
#include <cplusplus/Scope.h>
|
||||
#include <cplusplus/Names.h>
|
||||
#include <cplusplus/Symbols.h>
|
||||
#include <cplusplus/CoreTypes.h>
|
||||
#include <cplusplus/Literals.h>
|
||||
|
||||
#include <QVarLengthArray>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
namespace {
|
||||
|
||||
class ApplySubstitution
|
||||
{
|
||||
public:
|
||||
ApplySubstitution(Control *control, Symbol *symbol, const DeprecatedGenTemplateInstance::Substitution &substitution);
|
||||
~ApplySubstitution();
|
||||
|
||||
inline Control *control() const { return _control; }
|
||||
|
||||
FullySpecifiedType apply(const Name *name);
|
||||
FullySpecifiedType apply(const FullySpecifiedType &type);
|
||||
|
||||
int findSubstitution(const Identifier *id) const;
|
||||
FullySpecifiedType applySubstitution(int index) const;
|
||||
|
||||
private:
|
||||
class ApplyToType: protected TypeVisitor
|
||||
{
|
||||
public:
|
||||
ApplyToType(ApplySubstitution *q)
|
||||
: q(q) {}
|
||||
|
||||
FullySpecifiedType operator()(const FullySpecifiedType &ty)
|
||||
{
|
||||
FullySpecifiedType previousType = switchType(ty);
|
||||
accept(ty.type());
|
||||
return switchType(previousType);
|
||||
}
|
||||
|
||||
protected:
|
||||
using TypeVisitor::visit;
|
||||
|
||||
Control *control() const
|
||||
{ return q->control(); }
|
||||
|
||||
FullySpecifiedType switchType(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType previousType = _type;
|
||||
_type = type;
|
||||
return previousType;
|
||||
}
|
||||
|
||||
virtual void visit(VoidType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(IntegerType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(FloatType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(PointerToMemberType *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO; // ### TODO
|
||||
}
|
||||
|
||||
virtual void visit(PointerType *ptrTy)
|
||||
{
|
||||
_type.setType(control()->pointerType(q->apply(ptrTy->elementType())));
|
||||
}
|
||||
|
||||
virtual void visit(ReferenceType *refTy)
|
||||
{
|
||||
_type.setType(control()->referenceType(q->apply(refTy->elementType()), refTy->isRvalueReference()));
|
||||
}
|
||||
|
||||
virtual void visit(ArrayType *arrayTy)
|
||||
{
|
||||
_type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size()));
|
||||
}
|
||||
|
||||
virtual void visit(NamedType *ty)
|
||||
{
|
||||
FullySpecifiedType n = q->apply(ty->name());
|
||||
_type.setType(n.type());
|
||||
}
|
||||
|
||||
virtual void visit(Function *funTy)
|
||||
{
|
||||
Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name());
|
||||
fun->setEnclosingScope(funTy->enclosingScope());
|
||||
fun->setConst(funTy->isConst());
|
||||
fun->setVolatile(funTy->isVolatile());
|
||||
fun->setVirtual(funTy->isVirtual());
|
||||
fun->setOverride(funTy->isOverride());
|
||||
fun->setFinal(funTy->isFinal());
|
||||
fun->setAmbiguous(funTy->isAmbiguous());
|
||||
fun->setVariadic(funTy->isVariadic());
|
||||
|
||||
fun->setReturnType(q->apply(funTy->returnType()));
|
||||
|
||||
for (unsigned i = 0, argc = funTy->argumentCount(); i < argc; ++i) {
|
||||
Argument *originalArgument = funTy->argumentAt(i)->asArgument();
|
||||
Argument *arg = control()->newArgument(/*sourceLocation*/ 0,
|
||||
originalArgument->name());
|
||||
|
||||
arg->setType(q->apply(originalArgument->type()));
|
||||
arg->setInitializer(originalArgument->initializer());
|
||||
fun->addMember(arg);
|
||||
}
|
||||
|
||||
_type.setType(fun);
|
||||
}
|
||||
|
||||
virtual void visit(Namespace *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(Class *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(Enum *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ForwardClassDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCClass *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCProtocol *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCMethod *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardClassDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardProtocolDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
private:
|
||||
ApplySubstitution *q;
|
||||
FullySpecifiedType _type;
|
||||
QHash<Symbol *, FullySpecifiedType> _processed;
|
||||
};
|
||||
|
||||
class ApplyToName: protected NameVisitor
|
||||
{
|
||||
public:
|
||||
ApplyToName(ApplySubstitution *q): q(q) {}
|
||||
|
||||
FullySpecifiedType operator()(const Name *name)
|
||||
{
|
||||
FullySpecifiedType previousType = switchType(FullySpecifiedType());
|
||||
accept(name);
|
||||
return switchType(previousType);
|
||||
}
|
||||
|
||||
protected:
|
||||
Control *control() const
|
||||
{ return q->control(); }
|
||||
|
||||
int findSubstitution(const Identifier *id) const
|
||||
{ return q->findSubstitution(id); }
|
||||
|
||||
FullySpecifiedType applySubstitution(int index) const
|
||||
{ return q->applySubstitution(index); }
|
||||
|
||||
FullySpecifiedType switchType(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType previousType = _type;
|
||||
_type = type;
|
||||
return previousType;
|
||||
}
|
||||
|
||||
virtual void visit(const Identifier *name)
|
||||
{
|
||||
int index = findSubstitution(name->identifier());
|
||||
|
||||
if (index != -1)
|
||||
_type = applySubstitution(index);
|
||||
|
||||
else
|
||||
_type = control()->namedType(name);
|
||||
}
|
||||
|
||||
virtual void visit(const TemplateNameId *name)
|
||||
{
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
|
||||
for (unsigned i = 0; i < name->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(i);
|
||||
arguments[i] = q->apply(argTy);
|
||||
}
|
||||
|
||||
const TemplateNameId *templId = control()->templateNameId(name->identifier(),
|
||||
name->isSpecialization(),
|
||||
arguments.data(),
|
||||
arguments.size());
|
||||
_type = control()->namedType(templId);
|
||||
}
|
||||
|
||||
const Name *instantiate(const Name *name)
|
||||
{
|
||||
if (! name)
|
||||
return name;
|
||||
|
||||
if (const Identifier *nameId = name->asNameId()) {
|
||||
const Identifier *id = control()->identifier(nameId->chars(), nameId->size());
|
||||
return id;
|
||||
|
||||
} else if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
|
||||
for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
|
||||
++templateArgIndex) {
|
||||
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
|
||||
arguments[templateArgIndex] = q->apply(argTy);
|
||||
}
|
||||
const Identifier *id = control()->identifier(templId->identifier()->chars(),
|
||||
templId->identifier()->size());
|
||||
return control()->templateNameId(id, templId->isSpecialization(), arguments.data(),
|
||||
arguments.size());
|
||||
|
||||
} else if (const QualifiedNameId *qq = name->asQualifiedNameId()) {
|
||||
const Name *base = instantiate(qq->base());
|
||||
const Name *name = instantiate(qq->name());
|
||||
|
||||
return control()->qualifiedNameId(base, name);
|
||||
|
||||
} else if (const OperatorNameId *op = name->asOperatorNameId()) {
|
||||
return control()->operatorNameId(op->kind());
|
||||
|
||||
} else if (const ConversionNameId *c = name->asConversionNameId()) {
|
||||
FullySpecifiedType ty = q->apply(c->type());
|
||||
return control()->conversionNameId(ty);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void visit(const QualifiedNameId *name)
|
||||
{
|
||||
if (const Name *n = instantiate(name))
|
||||
_type = control()->namedType(n);
|
||||
}
|
||||
|
||||
virtual void visit(const DestructorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo.prettyName(name);
|
||||
}
|
||||
|
||||
virtual void visit(const OperatorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo.prettyName(name);
|
||||
}
|
||||
|
||||
virtual void visit(const ConversionNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo.prettyName(name);
|
||||
}
|
||||
|
||||
virtual void visit(const SelectorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo.prettyName(name);
|
||||
}
|
||||
|
||||
private:
|
||||
ApplySubstitution *q;
|
||||
FullySpecifiedType _type;
|
||||
};
|
||||
|
||||
public: // attributes
|
||||
Control *_control;
|
||||
Symbol *symbol;
|
||||
DeprecatedGenTemplateInstance::Substitution substitution;
|
||||
ApplyToType applyToType;
|
||||
ApplyToName applyToName;
|
||||
};
|
||||
|
||||
ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol,
|
||||
const DeprecatedGenTemplateInstance::Substitution &substitution)
|
||||
: _control(control), symbol(symbol),
|
||||
substitution(substitution),
|
||||
applyToType(this), applyToName(this)
|
||||
{ }
|
||||
|
||||
ApplySubstitution::~ApplySubstitution()
|
||||
{
|
||||
}
|
||||
|
||||
FullySpecifiedType ApplySubstitution::apply(const Name *name)
|
||||
{
|
||||
FullySpecifiedType ty = applyToName(name);
|
||||
return ty;
|
||||
}
|
||||
|
||||
FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType ty = applyToType(type);
|
||||
return ty;
|
||||
}
|
||||
|
||||
int ApplySubstitution::findSubstitution(const Identifier *id) const
|
||||
{
|
||||
Q_ASSERT(id != 0);
|
||||
|
||||
for (int index = 0; index < substitution.size(); ++index) {
|
||||
QPair<const Identifier *, FullySpecifiedType> s = substitution.at(index);
|
||||
|
||||
if (id->match(s.first))
|
||||
return index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
|
||||
{
|
||||
Q_ASSERT(index != -1);
|
||||
Q_ASSERT(index < substitution.size());
|
||||
|
||||
return substitution.at(index).second;
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution)
|
||||
: _control(control),
|
||||
_substitution(substitution)
|
||||
{ }
|
||||
|
||||
FullySpecifiedType DeprecatedGenTemplateInstance::gen(Symbol *symbol)
|
||||
{
|
||||
ApplySubstitution o(_control.data(), symbol, _substitution);
|
||||
return o.apply(symbol->type());
|
||||
}
|
||||
|
||||
FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *className, Symbol *candidate,
|
||||
QSharedPointer<Control> control)
|
||||
{
|
||||
if (className) {
|
||||
if (const TemplateNameId *templId = className->asTemplateNameId()) {
|
||||
if (Template *templ = candidate->enclosingTemplate()) {
|
||||
DeprecatedGenTemplateInstance::Substitution subst;
|
||||
|
||||
for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
|
||||
|
||||
if (i < templ->templateParameterCount()) {
|
||||
const Name *templArgName = templ->templateParameterAt(i)->name();
|
||||
|
||||
if (templArgName && templArgName->identifier()) {
|
||||
const Identifier *templArgId = templArgName->identifier();
|
||||
subst.append(qMakePair(templArgId, templArgTy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeprecatedGenTemplateInstance inst(control, subst);
|
||||
return inst.gen(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidate->type();
|
||||
}
|
@@ -28,41 +28,36 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TYPERESOLVER_H
|
||||
#define TYPERESOLVER_H
|
||||
#ifndef CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
|
||||
#define CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
|
||||
|
||||
#include "LookupContext.h"
|
||||
#include <cplusplus/TypeVisitor.h>
|
||||
#include <cplusplus/NameVisitor.h>
|
||||
#include <cplusplus/FullySpecifiedType.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class TypeResolver
|
||||
class CPLUSPLUS_EXPORT DeprecatedGenTemplateInstance
|
||||
{
|
||||
public:
|
||||
TypeResolver(CreateBindings &factory) : _factory(factory) {}
|
||||
void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding);
|
||||
static QList<LookupItem> resolveDeclInitializer(
|
||||
CreateBindings &factory, const Declaration *decl,
|
||||
const QSet<const Declaration *> &declarationsBeingResolved,
|
||||
const Identifier *id = 0);
|
||||
typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
|
||||
|
||||
public:
|
||||
static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
|
||||
|
||||
private:
|
||||
NamedType *getNamedType(FullySpecifiedType& type) const;
|
||||
DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
|
||||
FullySpecifiedType gen(Symbol *symbol);
|
||||
|
||||
QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
|
||||
LookupScope *binding) const;
|
||||
|
||||
static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope);
|
||||
|
||||
static bool isTypedefWithName(const Declaration *declaration, const Name *name);
|
||||
|
||||
bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
|
||||
Scope **scope, QSet<Symbol *>& visited);
|
||||
|
||||
CreateBindings &_factory;
|
||||
// binding has to be remembered in case of resolving typedefs for templates
|
||||
LookupScope *_binding;
|
||||
private:
|
||||
QSharedPointer<Control> _control;
|
||||
const Substitution _substitution;
|
||||
};
|
||||
|
||||
} // namespace CPlusPlus
|
||||
|
||||
#endif // TYPERESOLVER_H
|
||||
#endif // CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
|
@@ -532,7 +532,7 @@ void FindUsages::memInitializer(MemInitializerAST *ast)
|
||||
if (_currentScope->isFunction()) {
|
||||
Class *classScope = _currentScope->enclosingClass();
|
||||
if (! classScope) {
|
||||
if (LookupScope *binding = _context.lookupType(_currentScope)) {
|
||||
if (ClassOrNamespace *binding = _context.lookupType(_currentScope)) {
|
||||
foreach (Symbol *s, binding->symbols()) {
|
||||
if (Class *k = s->asClass()) {
|
||||
classScope = k;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,6 @@
|
||||
#include <cplusplus/Control.h>
|
||||
#include <cplusplus/Name.h>
|
||||
|
||||
#include <QEnableSharedFromThis>
|
||||
#include <QSet>
|
||||
#include <QMap>
|
||||
|
||||
@@ -59,78 +58,158 @@ struct FullyQualifiedName
|
||||
: fqn(fqn)
|
||||
{}
|
||||
};
|
||||
class LookupScopePrivate;
|
||||
class Instantiator;
|
||||
} // namespace Internal;
|
||||
|
||||
class CreateBindings;
|
||||
|
||||
class CPLUSPLUS_EXPORT LookupScope
|
||||
class CPLUSPLUS_EXPORT ClassOrNamespace
|
||||
{
|
||||
Q_DISABLE_COPY(LookupScope)
|
||||
Q_DISABLE_COPY(ClassOrNamespace)
|
||||
|
||||
LookupScope(CreateBindings *factory, LookupScope *parent);
|
||||
ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
|
||||
|
||||
public:
|
||||
~LookupScope();
|
||||
~ClassOrNamespace();
|
||||
|
||||
LookupScope *instantiationOrigin() const;
|
||||
const TemplateNameId *templateId() const;
|
||||
ClassOrNamespace *instantiationOrigin() const;
|
||||
|
||||
LookupScope *parent() const;
|
||||
QList<LookupScope *> usings() const;
|
||||
ClassOrNamespace *parent() const;
|
||||
QList<ClassOrNamespace *> usings() const;
|
||||
QList<Enum *> unscopedEnums() const;
|
||||
QList<Symbol *> symbols() const;
|
||||
|
||||
ClassOrNamespace *globalNamespace() const;
|
||||
|
||||
QList<LookupItem> lookup(const Name *name);
|
||||
QList<LookupItem> find(const Name *name);
|
||||
|
||||
LookupScope *lookupType(const Name *name);
|
||||
LookupScope *lookupType(const Name *name, Block *block);
|
||||
LookupScope *findType(const Name *name);
|
||||
LookupScope *findBlock(Block *block);
|
||||
ClassOrNamespace *lookupType(const Name *name);
|
||||
ClassOrNamespace *lookupType(const Name *name, Block *block);
|
||||
ClassOrNamespace *findType(const Name *name);
|
||||
ClassOrNamespace *findBlock(Block *block);
|
||||
|
||||
/// The class this LookupScope is based on.
|
||||
Class *rootClass() const;
|
||||
Symbol *lookupInScope(const QList<const Name *> &fullName);
|
||||
|
||||
/// The class this ClassOrNamespace is based on.
|
||||
Class *rootClass() const { return _rootClass; }
|
||||
|
||||
private:
|
||||
Internal::LookupScopePrivate *d;
|
||||
typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
|
||||
typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable;
|
||||
typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses;
|
||||
|
||||
/// \internal
|
||||
void flush();
|
||||
|
||||
/// \internal
|
||||
ClassOrNamespace *findOrCreateType(const Name *name, ClassOrNamespace *origin = 0,
|
||||
Class *clazz = 0);
|
||||
|
||||
ClassOrNamespace *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId);
|
||||
|
||||
void addTodo(Symbol *symbol);
|
||||
void addSymbol(Symbol *symbol);
|
||||
void addUnscopedEnum(Enum *e);
|
||||
void addUsing(ClassOrNamespace *u);
|
||||
void addNestedType(const Name *alias, ClassOrNamespace *e);
|
||||
|
||||
QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
|
||||
|
||||
void lookup_helper(const Name *name, ClassOrNamespace *binding,
|
||||
QList<LookupItem> *result,
|
||||
QSet<ClassOrNamespace *> *processed,
|
||||
const TemplateNameId *templateId);
|
||||
|
||||
ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
|
||||
bool searchInEnclosingScope, ClassOrNamespace *origin);
|
||||
|
||||
ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *processed,
|
||||
bool searchInEnclosingScope);
|
||||
|
||||
ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
|
||||
|
||||
void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
|
||||
Clone &cloner,
|
||||
Subst &subst,
|
||||
ClassOrNamespace *enclosingTemplateClassInstantiation);
|
||||
ClassOrNamespace *findSpecialization(const TemplateNameId *templId,
|
||||
const TemplateNameIdTable &specializations);
|
||||
|
||||
CreateBindings *_factory;
|
||||
ClassOrNamespace *_parent;
|
||||
QList<Symbol *> _symbols;
|
||||
QList<ClassOrNamespace *> _usings;
|
||||
Table _classOrNamespaces;
|
||||
QHash<Block *, ClassOrNamespace *> _blocks;
|
||||
QList<Enum *> _enums;
|
||||
QList<Symbol *> _todo;
|
||||
QSharedPointer<Control> _control;
|
||||
TemplateNameIdTable _specializations;
|
||||
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
|
||||
Anonymouses _anonymouses;
|
||||
QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses;
|
||||
|
||||
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
|
||||
|
||||
// it's an instantiation.
|
||||
const TemplateNameId *_templateId;
|
||||
ClassOrNamespace *_instantiationOrigin;
|
||||
|
||||
AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses;
|
||||
AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates;
|
||||
|
||||
Class *_rootClass;
|
||||
|
||||
class NestedClassInstantiator
|
||||
{
|
||||
public:
|
||||
NestedClassInstantiator(CreateBindings *factory, Clone &cloner, Subst &subst)
|
||||
: _factory(factory)
|
||||
, _cloner(cloner)
|
||||
, _subst(subst)
|
||||
{}
|
||||
void instantiate(ClassOrNamespace *enclosingTemplateClass,
|
||||
ClassOrNamespace *enclosingTemplateClassInstantiation);
|
||||
private:
|
||||
bool isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const;
|
||||
bool containsTemplateType(Declaration *declaration) const;
|
||||
bool containsTemplateType(Function *function) const;
|
||||
NamedType *findNamedType(Type *memberType) const;
|
||||
|
||||
QSet<ClassOrNamespace *> _alreadyConsideredNestedClassInstantiations;
|
||||
CreateBindings *_factory;
|
||||
Clone &_cloner;
|
||||
Subst &_subst;
|
||||
};
|
||||
|
||||
public:
|
||||
const Name *_name; // For debug
|
||||
|
||||
friend class Internal::LookupScopePrivate;
|
||||
friend class Internal::Instantiator;
|
||||
friend class CreateBindings;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT CreateBindings
|
||||
: protected SymbolVisitor
|
||||
, public QEnableSharedFromThis<CreateBindings>
|
||||
class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
|
||||
{
|
||||
Q_DISABLE_COPY(CreateBindings)
|
||||
|
||||
public:
|
||||
typedef QSharedPointer<CreateBindings> Ptr;
|
||||
|
||||
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
|
||||
virtual ~CreateBindings();
|
||||
|
||||
/// Returns the binding for the global namespace.
|
||||
LookupScope *globalNamespace() const;
|
||||
ClassOrNamespace *globalNamespace() const;
|
||||
|
||||
/// Finds the binding associated to the given symbol.
|
||||
LookupScope *lookupType(Symbol *symbol, LookupScope *enclosingBinding = 0);
|
||||
LookupScope *lookupType(const QList<const Name *> &path, LookupScope *enclosingBinding = 0);
|
||||
ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = 0);
|
||||
ClassOrNamespace *lookupType(const QList<const Name *> &path,
|
||||
ClassOrNamespace *enclosingBinding = 0);
|
||||
|
||||
/// Returns the Control that must be used to create temporary symbols.
|
||||
/// \internal
|
||||
QSharedPointer<Control> control() const
|
||||
{ return _control; }
|
||||
|
||||
Snapshot &snapshot()
|
||||
{ return _snapshot; }
|
||||
|
||||
/// Adds an expression document in order to keep their symbols and names alive
|
||||
void addExpressionDocument(Document::Ptr document)
|
||||
{ _expressionDocuments.append(document); }
|
||||
|
||||
bool expandTemplates() const
|
||||
{ return _expandTemplates; }
|
||||
void setExpandTemplates(bool expandTemplates)
|
||||
@@ -140,36 +219,28 @@ public:
|
||||
/// Store the result in \a results.
|
||||
/// \internal
|
||||
void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result,
|
||||
LookupScope *binding = 0);
|
||||
const TemplateNameId *templateId, ClassOrNamespace *binding);
|
||||
|
||||
/// Create bindings for the symbols reachable from \a rootSymbol.
|
||||
/// \internal
|
||||
void process(Symbol *rootSymbol, LookupScope *lookupScope);
|
||||
void process(Symbol *rootSymbol, ClassOrNamespace *classOrNamespace);
|
||||
|
||||
/// Create an empty LookupScope binding with the given \a parent.
|
||||
/// Create an empty ClassOrNamespace binding with the given \a parent.
|
||||
/// \internal
|
||||
LookupScope *allocLookupScope(LookupScope *parent, const Name *name);
|
||||
|
||||
FullySpecifiedType resolveTemplateArgument(Clone &cloner, Subst &subst,
|
||||
LookupScope *origin,
|
||||
const Template *specialization,
|
||||
const TemplateNameId *instantiation,
|
||||
unsigned index);
|
||||
void initializeSubst(Clone &cloner, Subst &subst, LookupScope *origin,
|
||||
const Template *specialization, const TemplateNameId *instantiation);
|
||||
ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent);
|
||||
|
||||
protected:
|
||||
using SymbolVisitor::visit;
|
||||
|
||||
/// Change the current LookupScope binding.
|
||||
LookupScope *switchCurrentLookupScope(LookupScope *lookupScope);
|
||||
/// Change the current ClassOrNamespace binding.
|
||||
ClassOrNamespace *switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace);
|
||||
|
||||
/// Enters the LookupScope binding associated with the given \a symbol.
|
||||
LookupScope *enterLookupScopeBinding(Symbol *symbol);
|
||||
/// Enters the ClassOrNamespace binding associated with the given \a symbol.
|
||||
ClassOrNamespace *enterClassOrNamespaceBinding(Symbol *symbol);
|
||||
|
||||
/// Enters a LookupScope binding for the given \a symbol in the global
|
||||
/// Enters a ClassOrNamespace binding for the given \a symbol in the global
|
||||
/// namespace binding.
|
||||
LookupScope *enterGlobalLookupScope(Symbol *symbol);
|
||||
ClassOrNamespace *enterGlobalClassOrNamespace(Symbol *symbol);
|
||||
|
||||
/// Creates bindings for the given \a document.
|
||||
void process(Document::Ptr document);
|
||||
@@ -178,7 +249,6 @@ protected:
|
||||
void process(Symbol *root);
|
||||
|
||||
virtual bool visit(Template *templ);
|
||||
virtual bool visit(ExplicitInstantiation *inst);
|
||||
virtual bool visit(Namespace *ns);
|
||||
virtual bool visit(Class *klass);
|
||||
virtual bool visit(ForwardClassDeclaration *klass);
|
||||
@@ -201,15 +271,16 @@ protected:
|
||||
virtual bool visit(ObjCMethod *);
|
||||
|
||||
private:
|
||||
Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
|
||||
Template *specialization) const;
|
||||
|
||||
Snapshot _snapshot;
|
||||
QSharedPointer<Control> _control;
|
||||
QList<Document::Ptr> _expressionDocuments;
|
||||
QSet<Namespace *> _processed;
|
||||
QList<LookupScope *> _entities;
|
||||
LookupScope *_globalNamespace;
|
||||
LookupScope *_currentLookupScope;
|
||||
QList<ClassOrNamespace *> _entities;
|
||||
ClassOrNamespace *_globalNamespace;
|
||||
ClassOrNamespace *_currentClassOrNamespace;
|
||||
bool _expandTemplates;
|
||||
int _depth;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT LookupContext
|
||||
@@ -223,7 +294,7 @@ public:
|
||||
LookupContext(Document::Ptr expressionDocument,
|
||||
Document::Ptr thisDocument,
|
||||
const Snapshot &snapshot,
|
||||
CreateBindings::Ptr bindings = CreateBindings::Ptr());
|
||||
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>());
|
||||
|
||||
LookupContext(const LookupContext &other);
|
||||
LookupContext &operator = (const LookupContext &other);
|
||||
@@ -233,25 +304,25 @@ public:
|
||||
Document::Ptr document(const QString &fileName) const;
|
||||
Snapshot snapshot() const;
|
||||
|
||||
LookupScope *globalNamespace() const;
|
||||
ClassOrNamespace *globalNamespace() const;
|
||||
|
||||
QList<LookupItem> lookup(const Name *name, Scope *scope) const;
|
||||
LookupScope *lookupType(const Name *name, Scope *scope,
|
||||
LookupScope *enclosingBinding = 0,
|
||||
ClassOrNamespace *lookupType(const Name *name, Scope *scope,
|
||||
ClassOrNamespace *enclosingBinding = 0,
|
||||
QSet<const Declaration *> typedefsBeingResolved
|
||||
= QSet<const Declaration *>()) const;
|
||||
LookupScope *lookupType(Symbol *symbol,
|
||||
LookupScope *enclosingBinding = 0) const;
|
||||
LookupScope *lookupParent(Symbol *symbol) const;
|
||||
ClassOrNamespace *lookupType(Symbol *symbol,
|
||||
ClassOrNamespace *enclosingBinding = 0) const;
|
||||
ClassOrNamespace *lookupParent(Symbol *symbol) const;
|
||||
|
||||
/// \internal
|
||||
CreateBindings::Ptr bindings() const
|
||||
QSharedPointer<CreateBindings> bindings() const
|
||||
{ return _bindings; }
|
||||
|
||||
static QList<const Name *> fullyQualifiedName(Symbol *symbol);
|
||||
static QList<const Name *> path(Symbol *symbol);
|
||||
|
||||
static const Name *minimalName(Symbol *symbol, LookupScope *target, Control *control);
|
||||
static const Name *minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control);
|
||||
|
||||
void setExpandTemplates(bool expandTemplates)
|
||||
{
|
||||
@@ -261,7 +332,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
QList<LookupItem> lookupByUsing(const Name *name, LookupScope *bindingScope) const;
|
||||
QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const;
|
||||
|
||||
// The current expression.
|
||||
Document::Ptr _expressionDocument;
|
||||
@@ -273,7 +344,7 @@ private:
|
||||
Snapshot _snapshot;
|
||||
|
||||
// Bindings
|
||||
CreateBindings::Ptr _bindings;
|
||||
QSharedPointer<CreateBindings> _bindings;
|
||||
|
||||
bool m_expandTemplates;
|
||||
};
|
||||
|
@@ -77,10 +77,10 @@ Scope *LookupItem::scope() const
|
||||
void LookupItem::setScope(Scope *scope)
|
||||
{ _scope = scope; }
|
||||
|
||||
LookupScope *LookupItem::binding() const
|
||||
ClassOrNamespace *LookupItem::binding() const
|
||||
{ return _binding; }
|
||||
|
||||
void LookupItem::setBinding(LookupScope *binding)
|
||||
void LookupItem::setBinding(ClassOrNamespace *binding)
|
||||
{ _binding = binding; }
|
||||
|
||||
bool LookupItem::operator == (const LookupItem &other) const
|
||||
|
@@ -37,7 +37,7 @@
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class LookupScope;
|
||||
class ClassOrNamespace;
|
||||
|
||||
class CPLUSPLUS_EXPORT LookupItem
|
||||
{
|
||||
@@ -63,8 +63,8 @@ public:
|
||||
/// Sets this item's scope.
|
||||
void setScope(Scope *scope);
|
||||
|
||||
LookupScope *binding() const;
|
||||
void setBinding(LookupScope *binding);
|
||||
ClassOrNamespace *binding() const;
|
||||
void setBinding(ClassOrNamespace *binding);
|
||||
|
||||
bool operator == (const LookupItem &other) const;
|
||||
bool operator != (const LookupItem &other) const;
|
||||
@@ -73,7 +73,7 @@ private:
|
||||
FullySpecifiedType _type;
|
||||
Scope *_scope;
|
||||
Symbol *_declaration;
|
||||
LookupScope *_binding;
|
||||
ClassOrNamespace *_binding;
|
||||
};
|
||||
|
||||
uint qHash(const CPlusPlus::LookupItem &result);
|
||||
|
@@ -32,9 +32,9 @@
|
||||
|
||||
#include "LookupContext.h"
|
||||
#include "Overview.h"
|
||||
#include "DeprecatedGenTemplateInstance.h"
|
||||
#include "CppRewriter.h"
|
||||
#include "TypeOfExpression.h"
|
||||
#include "TypeResolver.h"
|
||||
|
||||
#include <cplusplus/Control.h>
|
||||
#include <cplusplus/AST.h>
|
||||
@@ -75,6 +75,131 @@ static QList<T> removeDuplicates(const QList<T> &results)
|
||||
return uniqueList;
|
||||
}
|
||||
|
||||
class TypedefsResolver
|
||||
{
|
||||
public:
|
||||
TypedefsResolver(const LookupContext &context) : _context(context) {}
|
||||
void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
|
||||
{
|
||||
QSet<Symbol *> visited;
|
||||
_binding = binding;
|
||||
// Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
|
||||
// each other, each time enhancing the template argument and thus making it impossible to
|
||||
// use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
|
||||
// template parameters.
|
||||
unsigned maxDepth = 15;
|
||||
for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
|
||||
QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
|
||||
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
|
||||
|
||||
if (!findTypedef(namedTypeItems, type, scope, visited))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
NamedType *getNamedType(FullySpecifiedType& type) const
|
||||
{
|
||||
NamedType *namedTy = type->asNamedType();
|
||||
if (! namedTy) {
|
||||
if (PointerType *pointerTy = type->asPointerType())
|
||||
namedTy = pointerTy->elementType()->asNamedType();
|
||||
}
|
||||
return namedTy;
|
||||
}
|
||||
|
||||
QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
|
||||
ClassOrNamespace *binding) const
|
||||
{
|
||||
QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
|
||||
if (namedTypeItems.isEmpty()) {
|
||||
if (binding)
|
||||
namedTypeItems = binding->lookup(name);
|
||||
if (ClassOrNamespace *scopeCon = _context.lookupType(scope))
|
||||
namedTypeItems += scopeCon->lookup(name);
|
||||
}
|
||||
|
||||
return namedTypeItems;
|
||||
}
|
||||
|
||||
/// Return all typedefs with given name from given scope up to function scope.
|
||||
static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
|
||||
{
|
||||
QList<LookupItem> results;
|
||||
if (!scope)
|
||||
return results;
|
||||
Scope *enclosingBlockScope = 0;
|
||||
for (Block *block = scope->asBlock(); block;
|
||||
block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
|
||||
const unsigned memberCount = block->memberCount();
|
||||
for (unsigned i = 0; i < memberCount; ++i) {
|
||||
Symbol *symbol = block->memberAt(i);
|
||||
if (Declaration *declaration = symbol->asDeclaration()) {
|
||||
if (isTypedefWithName(declaration, name)) {
|
||||
LookupItem item;
|
||||
item.setDeclaration(declaration);
|
||||
item.setScope(block);
|
||||
item.setType(declaration->type());
|
||||
results.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
enclosingBlockScope = block->enclosingScope();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
static bool isTypedefWithName(const Declaration *declaration, const Name *name)
|
||||
{
|
||||
if (declaration->isTypedef()) {
|
||||
const Identifier *identifier = declaration->name()->identifier();
|
||||
if (name->identifier()->match(identifier))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
|
||||
Scope **scope, QSet<Symbol *>& visited)
|
||||
{
|
||||
bool foundTypedef = false;
|
||||
foreach (const LookupItem &it, namedTypeItems) {
|
||||
Symbol *declaration = it.declaration();
|
||||
if (declaration && declaration->isTypedef()) {
|
||||
if (visited.contains(declaration))
|
||||
break;
|
||||
visited.insert(declaration);
|
||||
|
||||
// continue working with the typedefed type and scope
|
||||
if (type->type()->isPointerType()) {
|
||||
*type = FullySpecifiedType(
|
||||
_context.bindings()->control()->pointerType(declaration->type()));
|
||||
} else if (type->type()->isReferenceType()) {
|
||||
*type = FullySpecifiedType(
|
||||
_context.bindings()->control()->referenceType(
|
||||
declaration->type(),
|
||||
declaration->type()->asReferenceType()->isRvalueReference()));
|
||||
} else {
|
||||
*type = declaration->type();
|
||||
}
|
||||
|
||||
*scope = it.scope();
|
||||
_binding = it.binding();
|
||||
foundTypedef = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return foundTypedef;
|
||||
}
|
||||
|
||||
const LookupContext &_context;
|
||||
// binding has to be remembered in case of resolving typedefs for templates
|
||||
ClassOrNamespace *_binding;
|
||||
};
|
||||
|
||||
static int evaluateFunctionArgument(const FullySpecifiedType &actualTy,
|
||||
const FullySpecifiedType &formalTy)
|
||||
{
|
||||
@@ -176,7 +301,7 @@ void ResolveExpression::addResults(const QList<LookupItem> &items)
|
||||
}
|
||||
|
||||
void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope,
|
||||
LookupScope *binding)
|
||||
ClassOrNamespace *binding)
|
||||
{
|
||||
LookupItem item;
|
||||
item.setType(ty);
|
||||
@@ -206,7 +331,7 @@ bool ResolveExpression::visit(BinaryExpressionAST *ast)
|
||||
if (d->core_declarator) {
|
||||
if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) {
|
||||
if (NameAST *nameAST = declaratorId->name) {
|
||||
if (LookupScope *binding = baseExpression(_results, T_ARROW)) {
|
||||
if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) {
|
||||
_results.clear();
|
||||
addResults(binding->lookup(nameAST->name));
|
||||
}
|
||||
@@ -487,14 +612,15 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
|
||||
added = true;
|
||||
} else if (namedTy != 0) {
|
||||
const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp);
|
||||
if (LookupScope *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) {
|
||||
foreach (const LookupItem &r, b->find(starOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
if (maybeValidPrototype(funTy, 0)) {
|
||||
FullySpecifiedType retTy = funTy->returnType().simplified();
|
||||
if (Function *proto = instantiate(b->templateId(), funTy)->asFunctionType()) {
|
||||
FullySpecifiedType retTy = proto->returnType().simplified();
|
||||
p.setType(retTy);
|
||||
p.setScope(funTy->enclosingScope());
|
||||
p.setScope(proto->enclosingScope());
|
||||
it.setValue(p);
|
||||
added = true;
|
||||
break;
|
||||
@@ -503,6 +629,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
it.remove();
|
||||
}
|
||||
@@ -526,6 +653,48 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class DeduceAutoCheck : public ASTVisitor
|
||||
{
|
||||
public:
|
||||
DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
|
||||
: ASTVisitor(tu), _id(id), _block(false)
|
||||
{
|
||||
accept(tu->ast());
|
||||
}
|
||||
|
||||
virtual bool preVisit(AST *)
|
||||
{
|
||||
if (_block)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(SimpleNameAST *ast)
|
||||
{
|
||||
if (ast->name
|
||||
&& ast->name->identifier()
|
||||
&& strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
|
||||
_block = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(MemberAccessAST *ast)
|
||||
{
|
||||
accept(ast->base_expression);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Identifier *_id;
|
||||
bool _block;
|
||||
};
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
{
|
||||
QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
|
||||
@@ -539,7 +708,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
if (item.declaration() == 0)
|
||||
continue;
|
||||
|
||||
if (item.type().isAuto() || item.type().isDecltype()) {
|
||||
if (item.type().isAuto()) {
|
||||
const Declaration *decl = item.declaration()->asDeclaration();
|
||||
if (!decl)
|
||||
continue;
|
||||
@@ -548,10 +717,53 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
if (_autoDeclarationsBeingResolved.contains(decl))
|
||||
continue;
|
||||
|
||||
newCandidates +=
|
||||
TypeResolver::resolveDeclInitializer(*_context.bindings(), decl,
|
||||
_autoDeclarationsBeingResolved << decl,
|
||||
ast->name->identifier());
|
||||
const StringLiteral *initializationString = decl->getInitializer();
|
||||
if (initializationString == 0)
|
||||
continue;
|
||||
|
||||
const QByteArray &initializer =
|
||||
QByteArray::fromRawData(initializationString->chars(),
|
||||
initializationString->size()).trimmed();
|
||||
|
||||
// Skip lambda-function initializers
|
||||
if (initializer.length() > 0 && initializer[0] == '[')
|
||||
continue;
|
||||
|
||||
TypeOfExpression exprTyper;
|
||||
exprTyper.setExpandTemplates(true);
|
||||
Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
|
||||
exprTyper.init(doc, _context.snapshot(), _context.bindings(),
|
||||
QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl);
|
||||
|
||||
Document::Ptr exprDoc =
|
||||
documentForExpression(exprTyper.preprocessedExpression(initializer));
|
||||
exprDoc->check();
|
||||
|
||||
DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit());
|
||||
if (deduceAuto._block)
|
||||
continue;
|
||||
|
||||
const QList<LookupItem> &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc,
|
||||
decl->enclosingScope());
|
||||
if (typeItems.empty())
|
||||
continue;
|
||||
|
||||
Clone cloner(_context.bindings()->control().data());
|
||||
|
||||
for (int n = 0; n < typeItems.size(); ++ n) {
|
||||
FullySpecifiedType newType = cloner.type(typeItems[n].type(), 0);
|
||||
if (n == 0) {
|
||||
item.setType(newType);
|
||||
item.setScope(typeItems[n].scope());
|
||||
item.setBinding(typeItems[n].binding());
|
||||
} else {
|
||||
LookupItem newItem(item);
|
||||
newItem.setType(newType);
|
||||
newItem.setScope(typeItems[n].scope());
|
||||
newItem.setBinding(typeItems[n].binding());
|
||||
newCandidates.push_back(newItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item.setType(item.declaration()->type());
|
||||
item.setScope(item.declaration()->enclosingScope());
|
||||
@@ -661,12 +873,14 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
Scope *scope = result.scope();
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
foreach (const LookupItem &r, b->find(functionCallOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount))
|
||||
addResult(funTy->returnType().simplified(), scope);
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount)) {
|
||||
if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
|
||||
addResult(proto->returnType().simplified(), scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -679,6 +893,14 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
// Constructor call
|
||||
FullySpecifiedType ctorTy = control()->namedType(classTy->name());
|
||||
addResult(ctorTy, scope);
|
||||
} else if (Template *templateTy = ty->asTemplateType()) {
|
||||
// template function
|
||||
if (Symbol *declaration = templateTy->declaration()) {
|
||||
if (Function *funTy = declaration->asFunction()) {
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount))
|
||||
addResult(funTy->returnType().simplified(), scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,8 +916,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
|
||||
FullySpecifiedType ty = result.type().simplified();
|
||||
Scope *scope = result.scope();
|
||||
|
||||
TypeResolver typeResolver(*_context.bindings());
|
||||
typeResolver.resolve(&ty, &scope, result.binding());
|
||||
TypedefsResolver typedefsResolver(_context);
|
||||
typedefsResolver.resolve(&ty, &scope, result.binding());
|
||||
|
||||
if (PointerType *ptrTy = ty->asPointerType()) {
|
||||
addResult(ptrTy->elementType().simplified(), scope);
|
||||
@@ -704,12 +926,13 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
|
||||
addResult(arrTy->elementType().simplified(), scope);
|
||||
|
||||
} else if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
foreach (const LookupItem &r, b->find(arrayAccessOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
|
||||
// ### TODO: check the actual arguments
|
||||
addResult(funTy->returnType().simplified(), scope);
|
||||
addResult(proto->returnType().simplified(), scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,7 +942,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<LookupItem> ResolveExpression::getMembers(LookupScope *binding, const Name *memberName) const
|
||||
QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
|
||||
{
|
||||
Q_UNUSED(binding);
|
||||
Q_UNUSED(memberName);
|
||||
@@ -788,17 +1011,17 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
|
||||
// Remember the access operator.
|
||||
const int accessOp = tokenKind(ast->access_token);
|
||||
|
||||
if (LookupScope *binding = baseExpression(baseResults, accessOp))
|
||||
if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp))
|
||||
addResults(binding->find(memberName));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope,
|
||||
LookupScope *enclosingBinding) const
|
||||
ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope,
|
||||
ClassOrNamespace *enclosingBinding) const
|
||||
{
|
||||
FullySpecifiedType ty = originalTy.simplified();
|
||||
LookupScope *binding = 0;
|
||||
ClassOrNamespace *binding = 0;
|
||||
|
||||
if (Class *klass = ty->asClassType()) {
|
||||
if (scope->isBlock())
|
||||
@@ -816,14 +1039,15 @@ LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy,
|
||||
return binding;
|
||||
}
|
||||
|
||||
LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
|
||||
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
|
||||
int accessOp,
|
||||
bool *replacedDotOperator) const
|
||||
{
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results...";
|
||||
int i = 0;
|
||||
TypeResolver typeResolver(*_context.bindings());
|
||||
Overview oo;
|
||||
TypedefsResolver typedefsResolver(_context);
|
||||
|
||||
foreach (const LookupItem &r, baseResults) {
|
||||
if (!r.type().type() || !r.scope())
|
||||
@@ -832,18 +1056,36 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
FullySpecifiedType originalType = ty;
|
||||
Scope *scope = r.scope();
|
||||
|
||||
if (Q_UNLIKELY(debug))
|
||||
if (Q_UNLIKELY(debug)) {
|
||||
qDebug("trying result #%d", ++i);
|
||||
qDebug() << "- before typedef resolving we have:" << oo(ty);
|
||||
}
|
||||
|
||||
typeResolver.resolve(&ty, &scope, r.binding());
|
||||
typedefsResolver.resolve(&ty, &scope, r.binding());
|
||||
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "- after typedef resolving:" << oo(ty);
|
||||
|
||||
if (accessOp == T_ARROW) {
|
||||
if (PointerType *ptrTy = ty->asPointerType()) {
|
||||
FullySpecifiedType type = ptrTy->elementType();
|
||||
if (LookupScope *binding = findClass(type, scope))
|
||||
if (ClassOrNamespace *binding
|
||||
= findClassForTemplateParameterInExpressionScope(r.binding(),
|
||||
type)) {
|
||||
return binding;
|
||||
}
|
||||
if (ClassOrNamespace *binding = findClass(type, scope))
|
||||
return binding;
|
||||
|
||||
} else if (LookupScope *binding = findClass(ty, scope, r.binding())) {
|
||||
} else {
|
||||
ClassOrNamespace *binding
|
||||
= findClassForTemplateParameterInExpressionScope(r.binding(),
|
||||
ty);
|
||||
|
||||
if (! binding)
|
||||
binding = findClass(ty, scope, r.binding());
|
||||
|
||||
if (binding){
|
||||
// lookup for overloads of operator->
|
||||
|
||||
const OperatorNameId *arrowOp
|
||||
@@ -854,10 +1096,16 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
continue;
|
||||
Scope *functionScope = overload->enclosingScope();
|
||||
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
FullySpecifiedType retTy = funTy->returnType().simplified();
|
||||
if (overload->type()->isFunctionType()) {
|
||||
FullySpecifiedType overloadTy
|
||||
= instantiate(binding->templateId(), overload);
|
||||
Function *instantiatedFunction = overloadTy->asFunctionType();
|
||||
Q_ASSERT(instantiatedFunction != 0);
|
||||
|
||||
typeResolver.resolve(&retTy, &functionScope, r.binding());
|
||||
FullySpecifiedType retTy
|
||||
= instantiatedFunction->returnType().simplified();
|
||||
|
||||
typedefsResolver.resolve(&retTy, &functionScope, r.binding());
|
||||
|
||||
if (! retTy->isPointerType() && ! retTy->isNamedType())
|
||||
continue;
|
||||
@@ -865,20 +1113,20 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
if (PointerType *ptrTy = retTy->asPointerType())
|
||||
retTy = ptrTy->elementType();
|
||||
|
||||
if (LookupScope *retBinding = findClass(retTy, functionScope))
|
||||
if (ClassOrNamespace *retBinding = findClass(retTy, functionScope))
|
||||
return retBinding;
|
||||
|
||||
if (scope != functionScope) {
|
||||
if (LookupScope *retBinding = findClass(retTy, scope))
|
||||
if (ClassOrNamespace *retBinding = findClass(retTy, scope))
|
||||
return retBinding;
|
||||
}
|
||||
|
||||
if (LookupScope *origin = binding->instantiationOrigin()) {
|
||||
if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
|
||||
foreach (Symbol *originSymbol, origin->symbols()) {
|
||||
Scope *originScope = originSymbol->asScope();
|
||||
if (originScope && originScope != scope
|
||||
&& originScope != functionScope) {
|
||||
if (LookupScope *retBinding
|
||||
if (ClassOrNamespace *retBinding
|
||||
= findClass(retTy, originScope))
|
||||
return retBinding;
|
||||
}
|
||||
@@ -887,6 +1135,7 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (accessOp == T_DOT) {
|
||||
if (replacedDotOperator) {
|
||||
*replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
|
||||
@@ -894,13 +1143,19 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
ty = ptrTy->elementType();
|
||||
}
|
||||
|
||||
LookupScope *enclosingBinding = 0;
|
||||
if (LookupScope *binding = r.binding()) {
|
||||
if (ClassOrNamespace *binding
|
||||
= findClassForTemplateParameterInExpressionScope(r.binding(),
|
||||
ty)) {
|
||||
return binding;
|
||||
}
|
||||
|
||||
ClassOrNamespace *enclosingBinding = 0;
|
||||
if (ClassOrNamespace *binding = r.binding()) {
|
||||
if (binding->instantiationOrigin())
|
||||
enclosingBinding = binding;
|
||||
}
|
||||
|
||||
if (LookupScope *binding = findClass(ty, scope, enclosingBinding))
|
||||
if (ClassOrNamespace *binding = findClass(ty, scope, enclosingBinding))
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
@@ -908,6 +1163,30 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClassOrNamespace *ResolveExpression::findClassForTemplateParameterInExpressionScope(
|
||||
ClassOrNamespace *resultBinding,
|
||||
const FullySpecifiedType &ty) const
|
||||
{
|
||||
if (resultBinding) {
|
||||
if (ClassOrNamespace *origin = resultBinding->instantiationOrigin()) {
|
||||
foreach (Symbol *originSymbol, origin->symbols()) {
|
||||
if (Scope *originScope = originSymbol->asScope()) {
|
||||
if (ClassOrNamespace *retBinding = findClass(ty, originScope))
|
||||
return retBinding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const
|
||||
{
|
||||
return DeprecatedGenTemplateInstance::instantiate(className, candidate,
|
||||
_context.bindings()->control());
|
||||
}
|
||||
|
||||
bool ResolveExpression::visit(PostIncrDecrAST *ast)
|
||||
{
|
||||
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
|
||||
@@ -921,7 +1200,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
|
||||
|
||||
foreach (const LookupItem &result, receiverResults) {
|
||||
FullySpecifiedType ty = result.type().simplified();
|
||||
LookupScope *binding = 0;
|
||||
ClassOrNamespace *binding = 0;
|
||||
|
||||
if (ObjCClass *clazz = ty->asObjCClassType()) {
|
||||
// static access, e.g.:
|
||||
|
@@ -53,25 +53,26 @@ public:
|
||||
QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
|
||||
QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
|
||||
|
||||
LookupScope *baseExpression(const QList<LookupItem> &baseResults,
|
||||
ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
|
||||
int accessOp,
|
||||
bool *replacedDotOperator = 0) const;
|
||||
|
||||
const LookupContext &context() const;
|
||||
|
||||
protected:
|
||||
LookupScope *findClass(const FullySpecifiedType &ty, Scope *scope,
|
||||
LookupScope *enclosingBinding = 0) const;
|
||||
ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope,
|
||||
ClassOrNamespace *enclosingBinding = 0) const;
|
||||
|
||||
QList<LookupItem> expression(ExpressionAST *ast);
|
||||
|
||||
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
|
||||
FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
|
||||
|
||||
QList<LookupItem> getMembers(LookupScope *binding, const Name *memberName) const;
|
||||
QList<LookupItem> getMembers(ClassOrNamespace *binding, const Name *memberName) const;
|
||||
|
||||
void thisObject();
|
||||
|
||||
void addResult(const FullySpecifiedType &ty, Scope *scope, LookupScope *binding = 0);
|
||||
void addResult(const FullySpecifiedType &ty, Scope *scope, ClassOrNamespace *binding = 0);
|
||||
void addResults(const QList<Symbol *> &symbols);
|
||||
void addResults(const QList<LookupItem> &items);
|
||||
|
||||
@@ -125,6 +126,10 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
ClassOrNamespace *findClassForTemplateParameterInExpressionScope(
|
||||
ClassOrNamespace *resultBinding,
|
||||
const FullySpecifiedType &ty) const;
|
||||
|
||||
Scope *_scope;
|
||||
const LookupContext& _context;
|
||||
Bind bind;
|
||||
|
@@ -50,7 +50,7 @@ TypeOfExpression::TypeOfExpression():
|
||||
}
|
||||
|
||||
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
|
||||
CreateBindings::Ptr bindings,
|
||||
QSharedPointer<CreateBindings> bindings,
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
|
||||
{
|
||||
m_thisDocument = thisDocument;
|
||||
@@ -62,7 +62,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot
|
||||
Q_ASSERT(m_bindings.isNull());
|
||||
m_bindings = bindings;
|
||||
if (m_bindings.isNull())
|
||||
m_bindings = CreateBindings::Ptr(new CreateBindings(thisDocument, snapshot));
|
||||
m_bindings = QSharedPointer<CreateBindings>(new CreateBindings(thisDocument, snapshot));
|
||||
|
||||
m_environment.clear();
|
||||
m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved;
|
||||
@@ -105,7 +105,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
|
||||
|
||||
m_scope = scope;
|
||||
|
||||
m_bindings->addExpressionDocument(document);
|
||||
m_documents.append(document);
|
||||
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
|
||||
Q_ASSERT(!m_bindings.isNull());
|
||||
m_lookupContext.setExpandTemplates(m_expandTemplates);
|
||||
@@ -122,7 +122,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
|
||||
|
||||
m_scope = scope;
|
||||
|
||||
m_bindings->addExpressionDocument(document);
|
||||
m_documents.append(document);
|
||||
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
|
||||
Q_ASSERT(!m_bindings.isNull());
|
||||
m_lookupContext.setExpandTemplates(m_expandTemplates);
|
||||
|
@@ -62,7 +62,7 @@ public:
|
||||
*/
|
||||
void init(Document::Ptr thisDocument,
|
||||
const Snapshot &snapshot,
|
||||
CreateBindings::Ptr bindings = CreateBindings::Ptr(),
|
||||
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(),
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved
|
||||
= QSet<const Declaration *>());
|
||||
|
||||
@@ -135,6 +135,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void processEnvironment(Document::Ptr doc, Environment *env,
|
||||
QSet<QString> *processed) const;
|
||||
|
||||
@@ -142,13 +143,20 @@ private:
|
||||
private:
|
||||
Document::Ptr m_thisDocument;
|
||||
Snapshot m_snapshot;
|
||||
CreateBindings::Ptr m_bindings;
|
||||
QSharedPointer<CreateBindings> m_bindings;
|
||||
ExpressionAST *m_ast;
|
||||
Scope *m_scope;
|
||||
LookupContext m_lookupContext;
|
||||
mutable QSharedPointer<Environment> m_environment;
|
||||
QSet<const Declaration *> m_autoDeclarationsBeingResolved;
|
||||
|
||||
bool m_expandTemplates;
|
||||
|
||||
// FIXME: This is a temporary hack to avoid dangling pointers.
|
||||
// Keep the expression documents and thus all the symbols and
|
||||
// their types alive until they are not needed any more.
|
||||
QList<Document::Ptr> m_documents;
|
||||
|
||||
QSet<const Declaration *> m_autoDeclarationsBeingResolved;
|
||||
};
|
||||
|
||||
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
|
||||
|
@@ -1,262 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "TypeResolver.h"
|
||||
#include "Overview.h"
|
||||
#include "TypeOfExpression.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
namespace {
|
||||
|
||||
class DeduceAutoCheck : public ASTVisitor
|
||||
{
|
||||
public:
|
||||
DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
|
||||
: ASTVisitor(tu), _id(id), _block(false)
|
||||
{
|
||||
accept(tu->ast());
|
||||
}
|
||||
|
||||
virtual bool preVisit(AST *)
|
||||
{
|
||||
if (_block)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(SimpleNameAST *ast)
|
||||
{
|
||||
if (ast->name
|
||||
&& ast->name->identifier()
|
||||
&& strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
|
||||
_block = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(MemberAccessAST *ast)
|
||||
{
|
||||
accept(ast->base_expression);
|
||||
return false;
|
||||
}
|
||||
|
||||
const Identifier *_id;
|
||||
bool _block;
|
||||
};
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
void TypeResolver::resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding)
|
||||
{
|
||||
QSet<Symbol *> visited;
|
||||
_binding = binding;
|
||||
// Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
|
||||
// each other, each time enhancing the template argument and thus making it impossible to
|
||||
// use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
|
||||
// template parameters.
|
||||
unsigned maxDepth = 15;
|
||||
Overview oo;
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "- before typedef resolving we have:" << oo(*type);
|
||||
for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
|
||||
QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
|
||||
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
|
||||
|
||||
if (!findTypedef(namedTypeItems, type, scope, visited))
|
||||
break;
|
||||
}
|
||||
if (Q_UNLIKELY(debug))
|
||||
qDebug() << "- after typedef resolving:" << oo(*type);
|
||||
}
|
||||
|
||||
NamedType *TypeResolver::getNamedType(FullySpecifiedType &type) const
|
||||
{
|
||||
NamedType *namedTy = type->asNamedType();
|
||||
if (! namedTy) {
|
||||
if (PointerType *pointerTy = type->asPointerType())
|
||||
namedTy = pointerTy->elementType()->asNamedType();
|
||||
}
|
||||
return namedTy;
|
||||
}
|
||||
|
||||
QList<LookupItem> TypeResolver::getNamedTypeItems(const Name *name, Scope *scope,
|
||||
LookupScope *binding) const
|
||||
{
|
||||
QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
|
||||
if (namedTypeItems.isEmpty()) {
|
||||
if (binding)
|
||||
namedTypeItems = binding->lookup(name);
|
||||
if (LookupScope *scopeCon = _factory.lookupType(scope)) {
|
||||
if (scopeCon != binding)
|
||||
namedTypeItems += scopeCon->lookup(name);
|
||||
}
|
||||
}
|
||||
|
||||
return namedTypeItems;
|
||||
}
|
||||
|
||||
/// Return all typedefs with given name from given scope up to function scope.
|
||||
QList<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
|
||||
{
|
||||
QList<LookupItem> results;
|
||||
if (!scope)
|
||||
return results;
|
||||
Scope *enclosingBlockScope = 0;
|
||||
for (Block *block = scope->asBlock(); block;
|
||||
block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
|
||||
const unsigned memberCount = block->memberCount();
|
||||
for (unsigned i = 0; i < memberCount; ++i) {
|
||||
Symbol *symbol = block->memberAt(i);
|
||||
if (Declaration *declaration = symbol->asDeclaration()) {
|
||||
if (isTypedefWithName(declaration, name)) {
|
||||
LookupItem item;
|
||||
item.setDeclaration(declaration);
|
||||
item.setScope(block);
|
||||
item.setType(declaration->type());
|
||||
results.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
enclosingBlockScope = block->enclosingScope();
|
||||
if (enclosingBlockScope) {
|
||||
// For lambda, step beyond the function to its enclosing block
|
||||
if (Function *enclosingFunction = enclosingBlockScope->asFunction()) {
|
||||
if (!enclosingFunction->name())
|
||||
enclosingBlockScope = enclosingBlockScope->enclosingScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// Resolves auto and decltype initializer string
|
||||
QList<LookupItem> TypeResolver::resolveDeclInitializer(
|
||||
CreateBindings &factory, const Declaration *decl,
|
||||
const QSet<const Declaration* > &declarationsBeingResolved,
|
||||
const Identifier *id)
|
||||
{
|
||||
const StringLiteral *initializationString = decl->getInitializer();
|
||||
if (initializationString == 0)
|
||||
return QList<LookupItem>();
|
||||
|
||||
const QByteArray &initializer =
|
||||
QByteArray::fromRawData(initializationString->chars(),
|
||||
initializationString->size()).trimmed();
|
||||
|
||||
// Skip lambda-function initializers
|
||||
if (initializer.length() > 0 && initializer[0] == '[')
|
||||
return QList<LookupItem>();
|
||||
|
||||
TypeOfExpression exprTyper;
|
||||
exprTyper.setExpandTemplates(true);
|
||||
Document::Ptr doc = factory.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
|
||||
exprTyper.init(doc, factory.snapshot(), factory.sharedFromThis(), declarationsBeingResolved);
|
||||
|
||||
Document::Ptr exprDoc =
|
||||
documentForExpression(exprTyper.preprocessedExpression(initializer));
|
||||
factory.addExpressionDocument(exprDoc);
|
||||
exprDoc->check();
|
||||
|
||||
if (id) {
|
||||
DeduceAutoCheck deduceAuto(id, exprDoc->translationUnit());
|
||||
if (deduceAuto._block)
|
||||
return QList<LookupItem>();
|
||||
}
|
||||
|
||||
return exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope());
|
||||
}
|
||||
|
||||
bool TypeResolver::isTypedefWithName(const Declaration *declaration, const Name *name)
|
||||
{
|
||||
if (declaration->isTypedef()) {
|
||||
const Identifier *identifier = declaration->name()->identifier();
|
||||
if (name->identifier()->match(identifier))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpecifiedType *type,
|
||||
Scope **scope, QSet<Symbol *> &visited)
|
||||
{
|
||||
foreach (const LookupItem &it, namedTypeItems) {
|
||||
Symbol *declaration = it.declaration();
|
||||
if (!declaration)
|
||||
continue;
|
||||
if (Template *specialization = declaration->asTemplate())
|
||||
declaration = specialization->declaration();
|
||||
if (!declaration || (!declaration->isTypedef() && !declaration->type().isDecltype()))
|
||||
continue;
|
||||
if (visited.contains(declaration))
|
||||
break;
|
||||
visited.insert(declaration);
|
||||
|
||||
// continue working with the typedefed type and scope
|
||||
if (type->type()->isPointerType()) {
|
||||
*type = FullySpecifiedType(
|
||||
_factory.control()->pointerType(declaration->type()));
|
||||
} else if (type->type()->isReferenceType()) {
|
||||
*type = FullySpecifiedType(
|
||||
_factory.control()->referenceType(
|
||||
declaration->type(),
|
||||
declaration->type()->asReferenceType()->isRvalueReference()));
|
||||
} else if (declaration->type().isDecltype()) {
|
||||
Declaration *decl = declaration->asDeclaration();
|
||||
const QList<LookupItem> resolved =
|
||||
resolveDeclInitializer(_factory, decl, QSet<const Declaration* >() << decl);
|
||||
if (!resolved.isEmpty()) {
|
||||
LookupItem item = resolved.first();
|
||||
*type = item.type();
|
||||
*scope = item.scope();
|
||||
_binding = item.binding();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
*type = it.type();
|
||||
}
|
||||
|
||||
*scope = it.scope();
|
||||
_binding = it.binding();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace CPlusPlus
|
@@ -36,7 +36,6 @@ HEADERS += \
|
||||
$$PWD/NamePrettyPrinter.h \
|
||||
$$PWD/TypeOfExpression.h \
|
||||
$$PWD/TypePrettyPrinter.h \
|
||||
$$PWD/TypeResolver.h \
|
||||
$$PWD/ResolveExpression.h \
|
||||
$$PWD/LookupItem.h \
|
||||
$$PWD/AlreadyConsideredClassContainer.h \
|
||||
@@ -45,6 +44,7 @@ HEADERS += \
|
||||
$$PWD/ASTPath.h \
|
||||
$$PWD/SnapshotSymbolVisitor.h \
|
||||
$$PWD/SymbolNameVisitor.h \
|
||||
$$PWD/DeprecatedGenTemplateInstance.h \
|
||||
$$PWD/FindUsages.h \
|
||||
$$PWD/DependencyTable.h \
|
||||
$$PWD/PreprocessorClient.h \
|
||||
@@ -67,7 +67,6 @@ SOURCES += \
|
||||
$$PWD/NamePrettyPrinter.cpp \
|
||||
$$PWD/TypeOfExpression.cpp \
|
||||
$$PWD/TypePrettyPrinter.cpp \
|
||||
$$PWD/TypeResolver.cpp \
|
||||
$$PWD/ResolveExpression.cpp \
|
||||
$$PWD/LookupItem.cpp \
|
||||
$$PWD/LookupContext.cpp \
|
||||
@@ -75,6 +74,7 @@ SOURCES += \
|
||||
$$PWD/ASTPath.cpp \
|
||||
$$PWD/SnapshotSymbolVisitor.cpp \
|
||||
$$PWD/SymbolNameVisitor.cpp \
|
||||
$$PWD/DeprecatedGenTemplateInstance.cpp \
|
||||
$$PWD/FindUsages.cpp \
|
||||
$$PWD/DependencyTable.cpp \
|
||||
$$PWD/PreprocessorClient.cpp \
|
||||
|
@@ -96,6 +96,7 @@ QtcLibrary {
|
||||
"CppRewriter.cpp", "CppRewriter.h",
|
||||
"cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h",
|
||||
"DependencyTable.cpp", "DependencyTable.h",
|
||||
"DeprecatedGenTemplateInstance.cpp", "DeprecatedGenTemplateInstance.h",
|
||||
"ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h",
|
||||
"FastPreprocessor.cpp", "FastPreprocessor.h",
|
||||
"FindUsages.cpp", "FindUsages.h",
|
||||
@@ -116,7 +117,6 @@ QtcLibrary {
|
||||
"SymbolNameVisitor.cpp", "SymbolNameVisitor.h",
|
||||
"TypeOfExpression.cpp", "TypeOfExpression.h",
|
||||
"TypePrettyPrinter.cpp", "TypePrettyPrinter.h",
|
||||
"TypeResolver.cpp", "TypeResolver.h",
|
||||
"cplusplus.qrc",
|
||||
"findcdbbreakpoint.cpp", "findcdbbreakpoint.h",
|
||||
"pp-cctype.h",
|
||||
|
@@ -795,7 +795,7 @@ static void buildContextProperties(
|
||||
Scope *typeScope = result.scope();
|
||||
if (!typeScope)
|
||||
typeScope = scope; // incorrect but may be an ok fallback
|
||||
LookupScope *binding = typeOf.context().lookupType(namedType->name(), typeScope);
|
||||
ClassOrNamespace *binding = typeOf.context().lookupType(namedType->name(), typeScope);
|
||||
if (binding && !binding->symbols().isEmpty()) {
|
||||
// find the best 'Class' symbol
|
||||
for (int i = binding->symbols().size() - 1; i >= 0; --i) {
|
||||
|
@@ -387,7 +387,7 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
|
||||
} else if (functionDefinitionSymbol) {
|
||||
const Snapshot snapshot = d->m_modelManager->snapshot();
|
||||
LookupContext context(d->m_lastSemanticInfo.doc, snapshot);
|
||||
LookupScope *binding = context.lookupType(functionDefinitionSymbol);
|
||||
ClassOrNamespace *binding = context.lookupType(functionDefinitionSymbol);
|
||||
const QList<LookupItem> declarations = context.lookup(functionDefinitionSymbol->name(),
|
||||
functionDefinitionSymbol->enclosingScope());
|
||||
|
||||
|
@@ -331,10 +331,10 @@ bool CppClass::operator==(const CppClass &other)
|
||||
|
||||
void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
|
||||
{
|
||||
typedef QPair<LookupScope *, CppClass *> Data;
|
||||
typedef QPair<ClassOrNamespace *, CppClass *> Data;
|
||||
|
||||
if (LookupScope *clazz = context.lookupType(declaration)) {
|
||||
QSet<LookupScope *> visited;
|
||||
if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
|
||||
QSet<ClassOrNamespace *> visited;
|
||||
|
||||
QQueue<Data> q;
|
||||
q.enqueue(qMakePair(clazz, this));
|
||||
@@ -342,8 +342,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
|
||||
Data current = q.dequeue();
|
||||
clazz = current.first;
|
||||
visited.insert(clazz);
|
||||
const QList<LookupScope *> &bases = clazz->usings();
|
||||
foreach (LookupScope *baseClass, bases) {
|
||||
const QList<ClassOrNamespace *> &bases = clazz->usings();
|
||||
foreach (ClassOrNamespace *baseClass, bases) {
|
||||
const QList<Symbol *> &symbols = baseClass->symbols();
|
||||
foreach (Symbol *symbol, symbols) {
|
||||
if (symbol->isClass() && (
|
||||
@@ -433,7 +433,7 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop
|
||||
}
|
||||
|
||||
if (typeName) {
|
||||
if (LookupScope *clazz = context.lookupType(typeName, scope)) {
|
||||
if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) {
|
||||
if (!clazz->symbols().isEmpty()) {
|
||||
Overview overview;
|
||||
Symbol *symbol = clazz->symbols().at(0);
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <cplusplus/ResolveExpression.h>
|
||||
#include <cplusplus/SimpleLexer.h>
|
||||
#include <cplusplus/Templates.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/functionutils.h>
|
||||
@@ -184,7 +183,7 @@ Class *VirtualFunctionHelper::staticClassOfFunctionCallExpression_internal() con
|
||||
const QList<LookupItem> items = m_typeOfExpression(memberAccessAST->base_expression,
|
||||
m_expressionDocument, m_scope);
|
||||
ResolveExpression resolveExpression(m_typeOfExpression.context());
|
||||
LookupScope *binding = resolveExpression.baseExpression(items, m_accessTokenKind);
|
||||
ClassOrNamespace *binding = resolveExpression.baseExpression(items, m_accessTokenKind);
|
||||
if (binding) {
|
||||
if (Class *klass = binding->rootClass()) {
|
||||
result = klass;
|
||||
|
@@ -607,7 +607,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(sourceContext);
|
||||
env.switchScope(sourceFunction->enclosingScope());
|
||||
LookupScope *targetCoN = targetContext.lookupType(targetFunction->enclosingScope());
|
||||
ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction->enclosingScope());
|
||||
if (!targetCoN)
|
||||
targetCoN = targetContext.globalNamespace();
|
||||
UseMinimalNames q(targetCoN);
|
||||
@@ -653,7 +653,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(sourceContext);
|
||||
env.switchScope(sourceFunction);
|
||||
LookupScope *targetCoN = targetContext.lookupType(targetFunction);
|
||||
ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction);
|
||||
if (!targetCoN)
|
||||
targetCoN = targetContext.globalNamespace();
|
||||
UseMinimalNames q(targetCoN);
|
||||
|
@@ -566,15 +566,15 @@ public:
|
||||
|
||||
// Determine base classes
|
||||
QList<const Class *> baseClasses;
|
||||
QQueue<LookupScope *> baseClassQueue;
|
||||
QSet<LookupScope *> visitedBaseClasses;
|
||||
if (LookupScope *clazz = interface.context().lookupType(m_classAST->symbol))
|
||||
QQueue<ClassOrNamespace *> baseClassQueue;
|
||||
QSet<ClassOrNamespace *> visitedBaseClasses;
|
||||
if (ClassOrNamespace *clazz = interface.context().lookupType(m_classAST->symbol))
|
||||
baseClassQueue.enqueue(clazz);
|
||||
while (!baseClassQueue.isEmpty()) {
|
||||
LookupScope *clazz = baseClassQueue.dequeue();
|
||||
ClassOrNamespace *clazz = baseClassQueue.dequeue();
|
||||
visitedBaseClasses.insert(clazz);
|
||||
const QList<LookupScope *> bases = clazz->usings();
|
||||
foreach (LookupScope *baseClass, bases) {
|
||||
const QList<ClassOrNamespace *> bases = clazz->usings();
|
||||
foreach (ClassOrNamespace *baseClass, bases) {
|
||||
foreach (Symbol *symbol, baseClass->symbols()) {
|
||||
Class *base = symbol->asClass();
|
||||
if (base
|
||||
@@ -768,7 +768,7 @@ public:
|
||||
const LookupContext targetContext(headerFile->cppDocument(), snapshot());
|
||||
|
||||
const Class *targetClass = m_classAST->symbol;
|
||||
LookupScope *targetCoN = targetContext.lookupType(targetClass->enclosingScope());
|
||||
ClassOrNamespace *targetCoN = targetContext.lookupType(targetClass->enclosingScope());
|
||||
if (!targetCoN)
|
||||
targetCoN = targetContext.globalNamespace();
|
||||
UseMinimalNames useMinimalNames(targetCoN);
|
||||
@@ -865,7 +865,7 @@ public:
|
||||
implementationDoc->translationUnit()->getPosition(insertPos, &line, &column);
|
||||
Scope *targetScope = implementationDoc->scopeAt(line, column);
|
||||
const LookupContext targetContext(implementationDoc, snapshot());
|
||||
LookupScope *targetCoN = targetContext.lookupType(targetScope);
|
||||
ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
|
||||
if (!targetCoN)
|
||||
targetCoN = targetContext.globalNamespace();
|
||||
|
||||
|
@@ -219,7 +219,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
|
||||
if (!q->base())
|
||||
return 0;
|
||||
|
||||
if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) {
|
||||
if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
|
||||
foreach (Symbol *s, binding->symbols()) {
|
||||
if (Class *matchingClass = s->asClass())
|
||||
return matchingClass;
|
||||
@@ -257,7 +257,7 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
|
||||
if (!q->base())
|
||||
return 0;
|
||||
|
||||
if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) {
|
||||
if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
|
||||
foreach (Symbol *s, binding->symbols()) {
|
||||
if (Namespace *matchingNamespace = s->asNamespace())
|
||||
return matchingNamespace;
|
||||
@@ -1331,7 +1331,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
|
||||
for (int i = path.size() - 1; i >= 0; --i) {
|
||||
if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
|
||||
Function *function = definition->symbol;
|
||||
LookupScope *b = interface.context().lookupType(function);
|
||||
ClassOrNamespace *b = interface.context().lookupType(function);
|
||||
if (b) {
|
||||
// Do we have a tr function?
|
||||
foreach (const LookupItem &r, b->find(trName)) {
|
||||
@@ -1592,7 +1592,7 @@ public:
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(context());
|
||||
env.switchScope(result.first().scope());
|
||||
LookupScope *con = typeOfExpression.context().lookupType(scope);
|
||||
ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
|
||||
if (!con)
|
||||
con = typeOfExpression.context().globalNamespace();
|
||||
UseMinimalNames q(con);
|
||||
@@ -2284,7 +2284,7 @@ Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
|
||||
if (Enum *e = type->asEnumType())
|
||||
return e;
|
||||
if (const NamedType *namedType = type->asNamedType()) {
|
||||
if (LookupScope *con = ctxt.lookupType(namedType->name(), result.scope())) {
|
||||
if (ClassOrNamespace *con = ctxt.lookupType(namedType->name(), result.scope())) {
|
||||
const QList<Enum *> enums = con->unscopedEnums();
|
||||
const Name *referenceName = namedType->name();
|
||||
if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId())
|
||||
@@ -2581,7 +2581,7 @@ public:
|
||||
Document::Ptr targetDoc = targetFile->cppDocument();
|
||||
Scope *targetScope = targetDoc->scopeAt(m_loc.line(), m_loc.column());
|
||||
LookupContext targetContext(targetDoc, snapshot());
|
||||
LookupScope *targetCoN = targetContext.lookupType(targetScope);
|
||||
ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
|
||||
if (!targetCoN)
|
||||
targetCoN = targetContext.globalNamespace();
|
||||
|
||||
@@ -3215,7 +3215,7 @@ public:
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(context());
|
||||
env.switchScope(refFunc);
|
||||
LookupScope *targetCoN = context().lookupType(refFunc->enclosingScope());
|
||||
ClassOrNamespace *targetCoN = context().lookupType(refFunc->enclosingScope());
|
||||
if (!targetCoN)
|
||||
targetCoN = context().globalNamespace();
|
||||
UseMinimalNames subs(targetCoN);
|
||||
@@ -4644,7 +4644,7 @@ QString definitionSignature(const CppQuickFixInterface *assist,
|
||||
QTC_ASSERT(func, return QString());
|
||||
|
||||
LookupContext cppContext(targetFile->cppDocument(), assist->snapshot());
|
||||
LookupScope *cppCoN = cppContext.lookupType(scope);
|
||||
ClassOrNamespace *cppCoN = cppContext.lookupType(scope);
|
||||
if (!cppCoN)
|
||||
cppCoN = cppContext.globalNamespace();
|
||||
SubstitutionEnvironment env;
|
||||
@@ -5125,7 +5125,7 @@ public:
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(context());
|
||||
env.switchScope(result.first().scope());
|
||||
LookupScope *con = typeOfExpression.context().lookupType(scope);
|
||||
ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
|
||||
if (!con)
|
||||
con = typeOfExpression.context().globalNamespace();
|
||||
UseMinimalNames q(con);
|
||||
@@ -5724,7 +5724,7 @@ PointerType *determineConvertedType(NamedType *namedType, const LookupContext &c
|
||||
{
|
||||
if (!namedType)
|
||||
return 0;
|
||||
if (LookupScope *binding = context.lookupType(namedType->name(), scope)) {
|
||||
if (ClassOrNamespace *binding = context.lookupType(namedType->name(), scope)) {
|
||||
if (Symbol *objectClassSymbol = skipForwardDeclarations(binding->symbols())) {
|
||||
if (Class *klass = objectClassSymbol->asClass()) {
|
||||
for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) {
|
||||
@@ -5782,7 +5782,7 @@ Class *senderOrReceiverClass(const CppQuickFixInterface &interface,
|
||||
NamedType *objectType = objectTypeBase->asNamedType();
|
||||
QTC_ASSERT(objectType, return 0);
|
||||
|
||||
LookupScope *objectClassCON = context.lookupType(objectType->name(), objectPointerScope);
|
||||
ClassOrNamespace *objectClassCON = context.lookupType(objectType->name(), objectPointerScope);
|
||||
QTC_ASSERT(objectClassCON, return 0);
|
||||
QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0);
|
||||
|
||||
@@ -5834,7 +5834,7 @@ bool findConnectReplacement(const CppQuickFixInterface &interface,
|
||||
|
||||
// Minimize qualification
|
||||
Control *control = context.bindings()->control().data();
|
||||
LookupScope *functionCON = context.lookupParent(scope);
|
||||
ClassOrNamespace *functionCON = context.lookupParent(scope);
|
||||
const Name *shortName = LookupContext::minimalName(method, functionCON, control);
|
||||
if (!shortName->asQualifiedNameId())
|
||||
shortName = control->qualifiedNameId(classOfMethod->name(), shortName);
|
||||
|
@@ -152,8 +152,8 @@ public:
|
||||
QTC_ASSERT(m_params.staticClass, return 0);
|
||||
QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0);
|
||||
|
||||
Class *functionsClass = m_finder.findMatchingClassDeclaration(
|
||||
m_params.function, m_params.snapshot, &m_params.typeOfExpression->context());
|
||||
Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function,
|
||||
m_params.snapshot);
|
||||
if (!functionsClass)
|
||||
return 0;
|
||||
|
||||
|
@@ -972,20 +972,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
|
||||
"template<class $T>\n"
|
||||
"using Foo = Bar<@T>;\n"
|
||||
);
|
||||
|
||||
QTest::newRow("qualifiedNames") << _(
|
||||
"struct C\n"
|
||||
"{\n"
|
||||
" struct Nested { int $member; };\n"
|
||||
" void f();\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void C::f()\n"
|
||||
"{\n"
|
||||
" C::Nested object;\n"
|
||||
" object.@member;\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
void CppEditorPlugin::test_FollowSymbolUnderCursor()
|
||||
@@ -1390,7 +1376,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_data()
|
||||
"template <class T> struct A { virtual void virt() {} };\n"
|
||||
"void f(A<int> *l) { l->$@virt(); }\n")
|
||||
<< (OverrideItemList()
|
||||
<< OverrideItem(QLatin1String("A<int>::virt"), 1));
|
||||
<< OverrideItem(QLatin1String("A::virt"), 1));
|
||||
|
||||
/// Check: Static type is nicely resolved, especially for QSharedPointers.
|
||||
QTest::newRow("QSharedPointer") << _(
|
||||
|
@@ -669,7 +669,7 @@ bool CheckSymbols::visit(NewExpressionAST *ast)
|
||||
if (highlightCtorDtorAsType) {
|
||||
accept(ast->new_type_id);
|
||||
} else {
|
||||
LookupScope *binding = 0;
|
||||
ClassOrNamespace *binding = 0;
|
||||
NameAST *nameAST = 0;
|
||||
if (ast->new_type_id) {
|
||||
for (SpecifierListAST *it = ast->new_type_id->type_specifier_list; it; it = it->next) {
|
||||
@@ -735,7 +735,7 @@ void CheckSymbols::checkNamespace(NameAST *name)
|
||||
unsigned line, column;
|
||||
getTokenStartPosition(name->firstToken(), &line, &column);
|
||||
|
||||
if (LookupScope *b = _context.lookupType(name->name, enclosingScope())) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(name->name, enclosingScope())) {
|
||||
foreach (Symbol *s, b->symbols()) {
|
||||
if (s->isNamespace())
|
||||
return;
|
||||
@@ -768,14 +768,14 @@ bool CheckSymbols::hasVirtualDestructor(Class *klass) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSymbols::hasVirtualDestructor(LookupScope *binding) const
|
||||
bool CheckSymbols::hasVirtualDestructor(ClassOrNamespace *binding) const
|
||||
{
|
||||
QSet<LookupScope *> processed;
|
||||
QList<LookupScope *> todo;
|
||||
QSet<ClassOrNamespace *> processed;
|
||||
QList<ClassOrNamespace *> todo;
|
||||
todo.append(binding);
|
||||
|
||||
while (!todo.isEmpty()) {
|
||||
LookupScope *b = todo.takeFirst();
|
||||
ClassOrNamespace *b = todo.takeFirst();
|
||||
if (b && !processed.contains(b)) {
|
||||
processed.insert(b);
|
||||
foreach (Symbol *s, b->symbols()) {
|
||||
@@ -857,7 +857,7 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
|
||||
{
|
||||
if (ast->name) {
|
||||
|
||||
LookupScope *binding = checkNestedName(ast);
|
||||
ClassOrNamespace *binding = checkNestedName(ast);
|
||||
|
||||
if (binding && ast->unqualified_name) {
|
||||
if (ast->unqualified_name->asDestructorName() != 0) {
|
||||
@@ -886,9 +886,9 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
LookupScope *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
|
||||
ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
|
||||
{
|
||||
LookupScope *binding = 0;
|
||||
ClassOrNamespace *binding = 0;
|
||||
|
||||
if (ast->name) {
|
||||
if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
|
||||
@@ -954,7 +954,7 @@ bool CheckSymbols::visit(MemInitializerAST *ast)
|
||||
{
|
||||
if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) {
|
||||
if (ast->name && enclosingFunction->symbol) {
|
||||
if (LookupScope *binding = _context.lookupType(enclosingFunction->symbol)) {
|
||||
if (ClassOrNamespace *binding = _context.lookupType(enclosingFunction->symbol)) {
|
||||
foreach (Symbol *s, binding->symbols()) {
|
||||
if (Class *klass = s->asClass()) {
|
||||
NameAST *nameAST = ast->name;
|
||||
@@ -1157,7 +1157,7 @@ void CheckSymbols::addUse(const Result &use)
|
||||
_usages.append(use);
|
||||
}
|
||||
|
||||
void CheckSymbols::addType(LookupScope *b, NameAST *ast)
|
||||
void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
|
||||
{
|
||||
unsigned startToken;
|
||||
if (!b || !acceptName(ast, &startToken))
|
||||
@@ -1296,8 +1296,12 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
|
||||
isConstructor = isConstructorDeclaration(c);
|
||||
|
||||
Function *funTy = c->type()->asFunctionType();
|
||||
if (!funTy) // Template function has an overridden type
|
||||
funTy = r.type()->asFunctionType();
|
||||
if (!funTy) {
|
||||
//Try to find a template function
|
||||
if (Template * t = r.type()->asTemplateType())
|
||||
if ((c = t->declaration()))
|
||||
funTy = c->type()->asFunctionType();
|
||||
}
|
||||
if (!funTy || funTy->isAmbiguous())
|
||||
continue; // TODO: add diagnostic messages and color call-operators calls too?
|
||||
|
||||
|
@@ -105,7 +105,7 @@ protected:
|
||||
const QList<Result> &otherUses);
|
||||
|
||||
bool hasVirtualDestructor(CPlusPlus::Class *klass) const;
|
||||
bool hasVirtualDestructor(CPlusPlus::LookupScope *binding) const;
|
||||
bool hasVirtualDestructor(CPlusPlus::ClassOrNamespace *binding) const;
|
||||
|
||||
bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
|
||||
bool warning(CPlusPlus::AST *ast, const QString &text);
|
||||
@@ -119,13 +119,13 @@ protected:
|
||||
|
||||
void checkNamespace(CPlusPlus::NameAST *name);
|
||||
void checkName(CPlusPlus::NameAST *ast, CPlusPlus::Scope *scope = 0);
|
||||
CPlusPlus::LookupScope *checkNestedName(CPlusPlus::QualifiedNameAST *ast);
|
||||
CPlusPlus::ClassOrNamespace *checkNestedName(CPlusPlus::QualifiedNameAST *ast);
|
||||
|
||||
void addUse(const Result &use);
|
||||
void addUse(unsigned tokenIndex, Kind kind);
|
||||
void addUse(CPlusPlus::NameAST *name, Kind kind);
|
||||
|
||||
void addType(CPlusPlus::LookupScope *b, CPlusPlus::NameAST *ast);
|
||||
void addType(CPlusPlus::ClassOrNamespace *b, CPlusPlus::NameAST *ast);
|
||||
|
||||
bool maybeAddTypeOrStatic(const QList<CPlusPlus::LookupItem> &candidates,
|
||||
CPlusPlus::NameAST *ast);
|
||||
|
@@ -328,17 +328,16 @@ void CppToolsPlugin::test_completion()
|
||||
actualCompletions.sort();
|
||||
expectedCompletions.sort();
|
||||
|
||||
QEXPECT_FAIL("template_as_base: typedef not available in derived",
|
||||
"We can live with that...", Abort);
|
||||
QEXPECT_FAIL("template_specialization_with_reference", "test of reverted change", Abort);
|
||||
QEXPECT_FAIL("specialization_multiple_arguments", "test of reverted change", Abort);
|
||||
QEXPECT_FAIL("specialization_with_default_value", "test of reverted change", Abort);
|
||||
QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
|
||||
QCOMPARE(actualCompletions, expectedCompletions);
|
||||
}
|
||||
|
||||
@@ -802,21 +801,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
<< QLatin1String("Data")
|
||||
<< QLatin1String("dataMember"));
|
||||
|
||||
QTest::newRow("explicit_instantiation") << _(
|
||||
"template<class T>\n"
|
||||
"struct Foo { T bar; };\n"
|
||||
"\n"
|
||||
"template class Foo<int>;\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Foo<int> foo;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("foo.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _(
|
||||
"struct Global\n"
|
||||
"{\n"
|
||||
@@ -1327,29 +1311,22 @@ void CppToolsPlugin::test_completion_data()
|
||||
<< QLatin1String("Template1"));
|
||||
|
||||
QTest::newRow("template_specialization_with_pointer") << _(
|
||||
"template <typename T> struct Temp { T variable; };\n"
|
||||
"template <typename T> struct Temp<T *> { T *pointer; };\n"
|
||||
"void func()\n"
|
||||
"template <typename T>\n"
|
||||
"struct Template\n"
|
||||
"{\n"
|
||||
" Temp<int*> templ;\n"
|
||||
" @\n"
|
||||
"}"
|
||||
" T variable;\n"
|
||||
"};\n"
|
||||
"template <typename T>\n"
|
||||
"struct Template<T *>\n"
|
||||
"{\n"
|
||||
" T *pointer;\n"
|
||||
"};\n"
|
||||
"Template<int*> templ;\n"
|
||||
"@\n"
|
||||
) << _("templ.") << (QStringList()
|
||||
<< QLatin1String("Temp")
|
||||
<< QLatin1String("Template")
|
||||
<< QLatin1String("pointer"));
|
||||
|
||||
QTest::newRow("template_specialization_with_reference") << _(
|
||||
"template <typename T> struct Temp { T variable; };\n"
|
||||
"template <typename T> struct Temp<T &> { T reference; };\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<int&> templ;\n"
|
||||
" @\n"
|
||||
"}"
|
||||
) << _("templ.") << (QStringList()
|
||||
<< QLatin1String("Temp")
|
||||
<< QLatin1String("reference"));
|
||||
|
||||
QTest::newRow("typedef_using_templates1") << _(
|
||||
"namespace NS1\n"
|
||||
"{\n"
|
||||
@@ -1572,29 +1549,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
<< QLatin1String("C")
|
||||
<< QLatin1String("m"));
|
||||
|
||||
QTest::newRow("type_and_using_declaration: type in nested namespace and using in global") << _(
|
||||
"namespace Ns {\n"
|
||||
"namespace Nested {\n"
|
||||
"struct Foo\n"
|
||||
"{\n"
|
||||
" void func();\n"
|
||||
" int m_bar;\n"
|
||||
"};\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"using namespace Ns::Nested;\n"
|
||||
"\n"
|
||||
"namespace Ns\n"
|
||||
"{\n"
|
||||
"void Foo::func()\n"
|
||||
"{\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
) << _("m_") << (QStringList()
|
||||
<< QLatin1String("m_bar"));
|
||||
|
||||
QTest::newRow("instantiate_template_with_anonymous_class") << _(
|
||||
"template <typename T>\n"
|
||||
"struct S\n"
|
||||
@@ -2568,21 +2522,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
) << _("ar") << (QStringList()
|
||||
<< QLatin1String("arg1"));
|
||||
|
||||
QTest::newRow("local_typedef_access_in_lambda") << _(
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" typedef Foo F;\n"
|
||||
" []() {\n"
|
||||
" F f;\n"
|
||||
" @\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
) << _("f.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("default_arguments_for_class_templates_and_base_class_QTCREATORBUG-12605") << _(
|
||||
"struct Foo { int foo; };\n"
|
||||
"template <typename T = Foo>\n"
|
||||
@@ -2689,78 +2628,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("S"));
|
||||
|
||||
QTest::newRow("partial_specialization") << _(
|
||||
"struct b {};\n"
|
||||
"template<class X, class Y> struct s { float f; };\n"
|
||||
"template<class X> struct s<X, b> { int i; };\n"
|
||||
"\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" s<int, b> var;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("var.") << (QStringList()
|
||||
<< QLatin1String("i")
|
||||
<< QLatin1String("s"));
|
||||
|
||||
// QTest::newRow("partial_specialization_with_pointer") << _(
|
||||
// "struct b {};\n"
|
||||
// "struct a : b {};\n"
|
||||
// "template<class X, class Y> struct s { float f; };\n"
|
||||
// "template<class X> struct s<X, b*> { int i; };\n"
|
||||
// "template<class X> struct s<X, a*> { char j; };\n"
|
||||
// "\n"
|
||||
// "void f()\n"
|
||||
// "{\n"
|
||||
// " s<int, a*> var;\n"
|
||||
// " @\n"
|
||||
// "}\n"
|
||||
// ) << _("var.") << (QStringList()
|
||||
// << QLatin1String("j")
|
||||
// << QLatin1String("s"));
|
||||
|
||||
QTest::newRow("partial_specialization_templated_argument") << _(
|
||||
"template<class T> struct t {};\n"
|
||||
"\n"
|
||||
"template<class> struct s { float f; };\n"
|
||||
"template<class X> struct s<t<X>> { int i; };\n"
|
||||
"\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" s<t<char>> var;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("var.") << (QStringList()
|
||||
<< QLatin1String("i")
|
||||
<< QLatin1String("s"));
|
||||
|
||||
QTest::newRow("specialization_multiple_arguments") << _(
|
||||
"class false_type {};\n"
|
||||
"class true_type {};\n"
|
||||
"template<class T1, class T2> class and_type { false_type f; };\n"
|
||||
"template<> class and_type<true_type, true_type> { true_type t; };\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" and_type<true_type, false_type> a;\n"
|
||||
" @;\n"
|
||||
"}\n"
|
||||
) << _("a.") << (QStringList()
|
||||
<< QLatin1String("f")
|
||||
<< QLatin1String("and_type"));
|
||||
|
||||
QTest::newRow("specialization_with_default_value") << _(
|
||||
"class Foo {};\n"
|
||||
"template<class T1 = Foo> class Temp;\n"
|
||||
"template<> class Temp<Foo> { int var; };\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<> t;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("t.") << (QStringList()
|
||||
<< QLatin1String("var")
|
||||
<< QLatin1String("Temp"));
|
||||
|
||||
QTest::newRow("auto_declaration_in_if_condition") << _(
|
||||
"struct Foo { int bar; };\n"
|
||||
"void fun() {\n"
|
||||
@@ -2966,28 +2833,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("instantiation_of_indirect_typedef") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Indirect { _Tp t; };\n"
|
||||
"\n"
|
||||
"template<typename T>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" typedef T MyT;\n"
|
||||
" typedef Indirect<MyT> indirect;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::indirect i;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("i.t.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));;
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits { };\n"
|
||||
@@ -3024,337 +2869,6 @@ void CppToolsPlugin::test_completion_data()
|
||||
) << _("t.p->") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("recursive_instantiation_of_template_type") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp { typedef _Tp value_type; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Temp<Foo> >::value_type::value_type *p;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("p->") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("recursive_instantiation_of_template_type_2") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp { typedef _Tp value_type; };\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Temp<Foo>::value_type>::value_type *p;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("p->") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("template_using_instantiation") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"using T = _Tp;\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" T<Foo> p;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("p.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("nested_template_using_instantiation") << _(
|
||||
"struct Parent {\n"
|
||||
" template<typename _Tp>\n"
|
||||
" using T = _Tp;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Parent::T<Foo> p;\n"
|
||||
" @;\n"
|
||||
"}\n"
|
||||
) << _("p.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("nested_template_using_instantiation_in_template_class") << _(
|
||||
"template<typename ParentT>\n"
|
||||
"struct Parent {\n"
|
||||
" template<typename _Tp>\n"
|
||||
" using T = _Tp;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Parent<Foo>::T<Foo> p;\n"
|
||||
" @;\n"
|
||||
"}\n"
|
||||
) << _("p.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("recursive_nested_template_using_instantiation") << _(
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"struct A { typedef Foo value_type; };\n"
|
||||
"\n"
|
||||
"template<typename T>\n"
|
||||
"struct Traits\n"
|
||||
"{\n"
|
||||
" typedef Foo value_type;\n"
|
||||
"\n"
|
||||
" template<typename _Tp>\n"
|
||||
" using U = T;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename T>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" typedef Traits<T> TraitsT;\n"
|
||||
" typedef typename T::value_type value_type;\n"
|
||||
" typedef typename TraitsT::template U<Foo> rebind;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" typename Temp<typename Temp<A>::rebind>::value_type p;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("p.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("qualified_name_in_nested_type") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Temp {\n"
|
||||
" struct Nested {\n"
|
||||
" typedef typename _Tp::Nested2 N;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo {\n"
|
||||
" struct Nested2 {\n"
|
||||
" int bar;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::Nested::N p;\n"
|
||||
" @;\n"
|
||||
"}\n"
|
||||
) << _("p.") << (QStringList()
|
||||
<< QLatin1String("Nested2")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("simple_decltype_declaration") << _(
|
||||
"struct Foo { int bar; };\n"
|
||||
"Foo foo;\n"
|
||||
"void fun() {\n"
|
||||
" decltype(foo) s;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("typedefed_decltype_declaration") << _(
|
||||
"struct Foo { int bar; };\n"
|
||||
"Foo foo;\n"
|
||||
"typedef decltype(foo) TypedefedFooWithDecltype;\n"
|
||||
"void fun() {\n"
|
||||
" TypedefedFooWithDecltype s;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("nested_instantiation_typedefed_decltype_declaration") << _(
|
||||
"template <typename T>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" struct Nested\n"
|
||||
" {\n"
|
||||
" static T f();\n"
|
||||
" typedef decltype(f()) type;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::Nested::type s;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("typedefed_decltype_of_template_function") << _(
|
||||
"template<typename T>\n"
|
||||
"static T f();\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" decltype(f<Foo>()) s;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("nested_instantiation_typedefed_decltype_declaration_of_template_function") << _(
|
||||
"template <typename T, typename D = T>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" struct Nested\n"
|
||||
" {\n"
|
||||
" template<typename U> static T* __test(...);\n"
|
||||
" typedef decltype(__test<D>(0)) type;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::Nested::type s;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("s.") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
|
||||
QTest::newRow("typedef for templates in namespace") << _(
|
||||
"namespace N {\n"
|
||||
"\n"
|
||||
"struct Data { int x; };\n"
|
||||
"template <typename T> struct Foo { T member; };\n"
|
||||
"typedef Foo<Data> Bar;\n"
|
||||
"\n"
|
||||
"} // N\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" N::Bar o;\n"
|
||||
" @\n"
|
||||
"}\n"
|
||||
) << _("o.member.") << (QStringList()
|
||||
<< QLatin1String("Data")
|
||||
<< QLatin1String("x"));
|
||||
|
||||
QTest::newRow("std vector") << _(
|
||||
"namespace std\n"
|
||||
"{\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct allocator\n"
|
||||
"{\n"
|
||||
" typedef _Tp value_type;\n"
|
||||
"\n"
|
||||
" template<typename _Tp1>\n"
|
||||
" struct rebind\n"
|
||||
" { typedef allocator<_Tp1> other; };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Alloc, typename _Tp>\n"
|
||||
"struct __alloctr_rebind\n"
|
||||
"{\n"
|
||||
" typedef typename _Alloc::template rebind<_Tp>::other __type;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Alloc>\n"
|
||||
"struct allocator_traits\n"
|
||||
"{\n"
|
||||
" typedef typename _Alloc::value_type value_type;\n"
|
||||
"\n"
|
||||
" template<typename _Tp>\n"
|
||||
" using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Iterator>\n"
|
||||
"struct iterator_traits { };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct iterator_traits<_Tp*>\n"
|
||||
"{\n"
|
||||
" typedef _Tp* pointer;\n"
|
||||
"};\n"
|
||||
"} // namespace std\n"
|
||||
"\n"
|
||||
"namespace __gnu_cxx\n"
|
||||
"{\n"
|
||||
"template<typename _Alloc>\n"
|
||||
"struct __alloc_traits\n"
|
||||
"{\n"
|
||||
" typedef _Alloc allocator_type;\n"
|
||||
" typedef std::allocator_traits<_Alloc> _Base_type;\n"
|
||||
" typedef typename _Alloc::value_type value_type;\n"
|
||||
"\n"
|
||||
" static value_type *_S_pointer_helper(...);\n"
|
||||
" typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n"
|
||||
" typedef __pointer pointer;\n"
|
||||
"\n"
|
||||
" template<typename _Tp>\n"
|
||||
" struct rebind\n"
|
||||
" { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Iterator, typename _Container>\n"
|
||||
"struct __normal_iterator\n"
|
||||
"{\n"
|
||||
" typedef std::iterator_traits<_Iterator> __traits_type;\n"
|
||||
" typedef typename __traits_type::pointer pointer;\n"
|
||||
"\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"} // namespace __gnu_cxx\n"
|
||||
"\n"
|
||||
"namespace std {\n"
|
||||
"template<typename _Tp, typename _Alloc>\n"
|
||||
"struct _Vector_Base\n"
|
||||
"{\n"
|
||||
" typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n"
|
||||
" rebind<_Tp>::other _Tp_alloc_type;\n"
|
||||
" typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n"
|
||||
" pointer;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Tp, typename _Alloc = std::allocator<_Tp> >\n"
|
||||
"struct vector : protected _Vector_Base<_Tp, _Alloc>\n"
|
||||
"{\n"
|
||||
" typedef _Vector_Base<_Tp, _Alloc> _Base;\n"
|
||||
" typedef typename _Base::pointer pointer;\n"
|
||||
" typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;\n"
|
||||
"};\n"
|
||||
"} // namespace std\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" std::vector<Foo>::iterator it;\n"
|
||||
" @;\n"
|
||||
"}\n"
|
||||
) << _("it.p->") << (QStringList()
|
||||
<< QLatin1String("Foo")
|
||||
<< QLatin1String("bar"));
|
||||
}
|
||||
|
||||
void CppToolsPlugin::test_completion_member_access_operator()
|
||||
|
@@ -753,7 +753,7 @@ bool canCompleteClassNameAt2ndOr4thConnectArgument(
|
||||
|| eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma();
|
||||
}
|
||||
|
||||
LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem,
|
||||
ClassOrNamespace *classOrNamespaceFromLookupItem(const LookupItem &lookupItem,
|
||||
const LookupContext &context)
|
||||
{
|
||||
const Name *name = 0;
|
||||
@@ -783,7 +783,7 @@ LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem,
|
||||
|
||||
Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context)
|
||||
{
|
||||
LookupScope *b = lookupScopeFromLookupItem(lookupItem, context);
|
||||
ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
|
||||
if (!b)
|
||||
return 0;
|
||||
|
||||
@@ -796,7 +796,7 @@ Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &co
|
||||
|
||||
const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context)
|
||||
{
|
||||
LookupScope *target = context.lookupType(targetScope);
|
||||
ClassOrNamespace *target = context.lookupType(targetScope);
|
||||
if (!target)
|
||||
target = context.globalNamespace();
|
||||
return context.minimalName(symbol, target, context.bindings()->control().data());
|
||||
@@ -1219,12 +1219,12 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
|
||||
ty = ty->asPointerType()->elementType().simplified();
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
LookupScope *binding = lookupContext.lookupType(namedTy->name(), item.scope());
|
||||
ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope());
|
||||
completeObjCMsgSend(binding, false);
|
||||
}
|
||||
} else {
|
||||
if (ObjCClass *clazz = ty->asObjCClassType()) {
|
||||
LookupScope *binding = lookupContext.lookupType(clazz->name(), item.scope());
|
||||
ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope());
|
||||
completeObjCMsgSend(binding, true);
|
||||
}
|
||||
}
|
||||
@@ -1273,7 +1273,7 @@ void InternalCppCompletionAssistProcessor::addCompletionItem(Symbol *symbol, int
|
||||
}
|
||||
}
|
||||
|
||||
void InternalCppCompletionAssistProcessor::completeObjCMsgSend(LookupScope *binding,
|
||||
void InternalCppCompletionAssistProcessor::completeObjCMsgSend(ClassOrNamespace *binding,
|
||||
bool staticClassAccess)
|
||||
{
|
||||
QList<Scope*> memberScopes;
|
||||
@@ -1542,26 +1542,26 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
|
||||
return !m_completions.isEmpty();
|
||||
}
|
||||
|
||||
QList<LookupScope *> usingBindings;
|
||||
LookupScope *currentBinding = 0;
|
||||
QList<ClassOrNamespace *> usingBindings;
|
||||
ClassOrNamespace *currentBinding = 0;
|
||||
|
||||
for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) {
|
||||
if (Block *block = scope->asBlock()) {
|
||||
if (LookupScope *binding = context.lookupType(scope)) {
|
||||
if (ClassOrNamespace *binding = context.lookupType(scope)) {
|
||||
for (unsigned i = 0; i < scope->memberCount(); ++i) {
|
||||
Symbol *member = scope->memberAt(i);
|
||||
if (member->isEnum()) {
|
||||
if (LookupScope *b = binding->findBlock(block))
|
||||
if (ClassOrNamespace *b = binding->findBlock(block))
|
||||
completeNamespace(b);
|
||||
}
|
||||
if (!member->name())
|
||||
continue;
|
||||
if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
|
||||
if (LookupScope *b = binding->lookupType(u->name()))
|
||||
if (ClassOrNamespace *b = binding->lookupType(u->name()))
|
||||
usingBindings.append(b);
|
||||
} else if (Class *c = member->asClass()) {
|
||||
if (c->name()->isAnonymousNameId()) {
|
||||
if (LookupScope *b = binding->findBlock(block))
|
||||
if (ClassOrNamespace *b = binding->findBlock(block))
|
||||
completeClass(b);
|
||||
}
|
||||
}
|
||||
@@ -1588,7 +1588,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
|
||||
}
|
||||
|
||||
for (; currentBinding; currentBinding = currentBinding->parent()) {
|
||||
foreach (LookupScope* u, currentBinding->usings())
|
||||
foreach (ClassOrNamespace* u, currentBinding->usings())
|
||||
usingBindings.append(u);
|
||||
|
||||
const QList<Symbol *> symbols = currentBinding->symbols();
|
||||
@@ -1601,7 +1601,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
|
||||
}
|
||||
}
|
||||
|
||||
foreach (LookupScope *b, usingBindings)
|
||||
foreach (ClassOrNamespace *b, usingBindings)
|
||||
completeNamespace(b);
|
||||
|
||||
addKeywords();
|
||||
@@ -1624,7 +1624,7 @@ bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem
|
||||
if (!m_interface->languageFeatures().objCEnabled)
|
||||
replaceDotForArrow = &m_model->m_replaceDotForArrow;
|
||||
|
||||
if (LookupScope *binding =
|
||||
if (ClassOrNamespace *binding =
|
||||
resolveExpression.baseExpression(baseResults,
|
||||
m_model->m_completionOperator,
|
||||
replaceDotForArrow)) {
|
||||
@@ -1648,27 +1648,27 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
|
||||
Scope *scope = result.scope();
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (LookupScope *b = context.lookupType(namedTy->name(), scope)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
|
||||
completeClass(b);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (Class *classTy = ty->asClassType()) {
|
||||
if (LookupScope *b = context.lookupType(classTy)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(classTy)) {
|
||||
completeClass(b);
|
||||
break;
|
||||
}
|
||||
|
||||
// it can be class defined inside a block
|
||||
if (classTy->enclosingScope()->isBlock()) {
|
||||
if (LookupScope *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
|
||||
if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
|
||||
completeClass(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (Namespace *nsTy = ty->asNamespaceType()) {
|
||||
if (LookupScope *b = context.lookupType(nsTy)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(nsTy)) {
|
||||
completeNamespace(b);
|
||||
break;
|
||||
}
|
||||
@@ -1676,7 +1676,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
|
||||
} else if (Template *templ = ty->asTemplateType()) {
|
||||
if (!result.binding())
|
||||
continue;
|
||||
if (LookupScope *b = result.binding()->lookupType(templ->name())) {
|
||||
if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) {
|
||||
completeClass(b);
|
||||
break;
|
||||
}
|
||||
@@ -1684,16 +1684,16 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
|
||||
} else if (Enum *e = ty->asEnumType()) {
|
||||
// it can be class defined inside a block
|
||||
if (e->enclosingScope()->isBlock()) {
|
||||
if (LookupScope *b = context.lookupType(e)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(e)) {
|
||||
Block *block = e->enclosingScope()->asBlock();
|
||||
if (LookupScope *bb = b->findBlock(block)) {
|
||||
if (ClassOrNamespace *bb = b->findBlock(block)) {
|
||||
completeNamespace(bb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LookupScope *b = context.lookupType(e)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(e)) {
|
||||
completeNamespace(b);
|
||||
break;
|
||||
}
|
||||
@@ -1704,14 +1704,14 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
|
||||
return !m_completions.isEmpty();
|
||||
}
|
||||
|
||||
void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b)
|
||||
void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b)
|
||||
{
|
||||
QSet<LookupScope *> bindingsVisited;
|
||||
QList<LookupScope *> bindingsToVisit;
|
||||
QSet<ClassOrNamespace *> bindingsVisited;
|
||||
QList<ClassOrNamespace *> bindingsToVisit;
|
||||
bindingsToVisit.append(b);
|
||||
|
||||
while (!bindingsToVisit.isEmpty()) {
|
||||
LookupScope *binding = bindingsToVisit.takeFirst();
|
||||
ClassOrNamespace *binding = bindingsToVisit.takeFirst();
|
||||
if (!binding || bindingsVisited.contains(binding))
|
||||
continue;
|
||||
|
||||
@@ -1744,14 +1744,14 @@ void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b)
|
||||
}
|
||||
}
|
||||
|
||||
void InternalCppCompletionAssistProcessor::completeClass(LookupScope *b, bool staticLookup)
|
||||
void InternalCppCompletionAssistProcessor::completeClass(ClassOrNamespace *b, bool staticLookup)
|
||||
{
|
||||
QSet<LookupScope *> bindingsVisited;
|
||||
QList<LookupScope *> bindingsToVisit;
|
||||
QSet<ClassOrNamespace *> bindingsVisited;
|
||||
QList<ClassOrNamespace *> bindingsToVisit;
|
||||
bindingsToVisit.append(b);
|
||||
|
||||
while (!bindingsToVisit.isEmpty()) {
|
||||
LookupScope *binding = bindingsToVisit.takeFirst();
|
||||
ClassOrNamespace *binding = bindingsToVisit.takeFirst();
|
||||
if (!binding || bindingsVisited.contains(binding))
|
||||
continue;
|
||||
|
||||
@@ -1838,16 +1838,16 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
|
||||
|
||||
QSet<QString> signatures;
|
||||
foreach (const LookupItem &lookupItem, results) {
|
||||
LookupScope *b = lookupScopeFromLookupItem(lookupItem, context);
|
||||
ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
QList<LookupScope *>todo;
|
||||
QSet<LookupScope *> processed;
|
||||
QList<ClassOrNamespace *>todo;
|
||||
QSet<ClassOrNamespace *> processed;
|
||||
QList<Scope *> scopes;
|
||||
todo.append(b);
|
||||
while (!todo.isEmpty()) {
|
||||
LookupScope *binding = todo.takeLast();
|
||||
ClassOrNamespace *binding = todo.takeLast();
|
||||
if (!processed.contains(binding)) {
|
||||
processed.insert(binding);
|
||||
|
||||
@@ -2063,7 +2063,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
|
||||
Scope *scope = result.scope();
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (LookupScope *b = context.lookupType(namedTy->name(), scope)) {
|
||||
if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
|
||||
foreach (const LookupItem &r, b->lookup(functionCallOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
FullySpecifiedType overloadTy = overload->type().simplified();
|
||||
@@ -2145,7 +2145,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
|
||||
SubstitutionEnvironment env;
|
||||
env.setContext(context);
|
||||
env.switchScope(sc);
|
||||
LookupScope *targetCoN = context.lookupType(sc);
|
||||
ClassOrNamespace *targetCoN = context.lookupType(sc);
|
||||
if (!targetCoN)
|
||||
targetCoN = context.globalNamespace();
|
||||
UseMinimalNames q(targetCoN);
|
||||
|
@@ -53,7 +53,7 @@
|
||||
|
||||
namespace CPlusPlus {
|
||||
class LookupItem;
|
||||
class LookupScope;
|
||||
class ClassOrNamespace;
|
||||
class Function;
|
||||
class LookupContext;
|
||||
} // namespace CPlusPlus
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
const QString &expression,
|
||||
int endOfExpression);
|
||||
|
||||
void completeObjCMsgSend(CPlusPlus::LookupScope *binding, bool staticClassAccess);
|
||||
void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, bool staticClassAccess);
|
||||
bool completeInclude(const QTextCursor &cursor);
|
||||
void completeInclude(const QString &realPath, const QStringList &suffixes);
|
||||
void completePreprocessor();
|
||||
@@ -130,8 +130,8 @@ private:
|
||||
bool toolTipOnly);
|
||||
bool completeMember(const QList<CPlusPlus::LookupItem> &results);
|
||||
bool completeScope(const QList<CPlusPlus::LookupItem> &results);
|
||||
void completeNamespace(CPlusPlus::LookupScope *binding);
|
||||
void completeClass(CPlusPlus::LookupScope *b, bool staticLookup = true);
|
||||
void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
|
||||
void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true);
|
||||
void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup);
|
||||
enum CompleteQtMethodMode {
|
||||
CompleteQt4Signals,
|
||||
|
@@ -108,7 +108,7 @@ bool isOwnershipRAIIType(Symbol *symbol, const LookupContext &context)
|
||||
Declaration *declaration = symbol->asDeclaration();
|
||||
const NamedType *namedType = declaration->type()->asNamedType();
|
||||
if (namedType) {
|
||||
LookupScope *clazz = context.lookupType(namedType->name(),
|
||||
ClassOrNamespace *clazz = context.lookupType(namedType->name(),
|
||||
declaration->enclosingScope());
|
||||
if (clazz && !clazz->symbols().isEmpty()) {
|
||||
Overview overview;
|
||||
|
@@ -151,7 +151,7 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
|
||||
|
||||
QList<Function *> viableFunctions;
|
||||
|
||||
LookupScope *enclosingType = context.lookupType(declaration);
|
||||
ClassOrNamespace *enclosingType = context.lookupType(declaration);
|
||||
if (!enclosingType)
|
||||
continue; // nothing to do
|
||||
|
||||
@@ -214,15 +214,13 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
|
||||
return 0;
|
||||
}
|
||||
|
||||
Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot,
|
||||
const LookupContext *context)
|
||||
Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot)
|
||||
{
|
||||
if (!declaration->identifier())
|
||||
return 0;
|
||||
|
||||
QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
|
||||
|
||||
const bool useLocalContext = !context;
|
||||
foreach (const QString &file, fileIterationOrder(declFile, snapshot)) {
|
||||
Document::Ptr doc = snapshot.document(file);
|
||||
if (!doc) {
|
||||
@@ -234,13 +232,9 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna
|
||||
declaration->identifier()->size()))
|
||||
continue;
|
||||
|
||||
QScopedPointer<LookupContext> localContext;
|
||||
if (useLocalContext) {
|
||||
localContext.reset(new LookupContext(doc, snapshot));
|
||||
context = localContext.data();
|
||||
}
|
||||
LookupContext context(doc, snapshot);
|
||||
|
||||
LookupScope *type = context->lookupType(declaration);
|
||||
ClassOrNamespace *type = context.lookupType(declaration);
|
||||
if (!type)
|
||||
continue;
|
||||
|
||||
@@ -289,7 +283,7 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
|
||||
if (!functionName)
|
||||
return;
|
||||
|
||||
LookupScope *binding = 0;
|
||||
ClassOrNamespace *binding = 0;
|
||||
const QualifiedNameId *qName = functionName->asQualifiedNameId();
|
||||
if (qName) {
|
||||
if (qName->base())
|
||||
|
@@ -61,8 +61,7 @@ public:
|
||||
bool strict = false);
|
||||
|
||||
CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration,
|
||||
const CPlusPlus::Snapshot &snapshot,
|
||||
const CPlusPlus::LookupContext *context = 0);
|
||||
const CPlusPlus::Snapshot &snapshot);
|
||||
|
||||
void findMatchingDeclaration(const CPlusPlus::LookupContext &context,
|
||||
CPlusPlus::Function *functionType,
|
||||
|
@@ -65,12 +65,12 @@ class MkVisitor: protected SymbolVisitor
|
||||
{
|
||||
const LookupContext &context;
|
||||
Overview oo;
|
||||
QList<LookupScope *> interfaces;
|
||||
QList<LookupScope *> nodes;
|
||||
QList<ClassOrNamespace *> interfaces;
|
||||
QList<ClassOrNamespace *> nodes;
|
||||
|
||||
bool isMiscNode(LookupScope *b) const
|
||||
bool isMiscNode(ClassOrNamespace *b) const
|
||||
{
|
||||
foreach (LookupScope *u, b->usings()) {
|
||||
foreach (ClassOrNamespace *u, b->usings()) {
|
||||
if (oo(u->symbols().first()->name()) == QLatin1String("AST"))
|
||||
return true;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ class MkVisitor: protected SymbolVisitor
|
||||
return false;
|
||||
}
|
||||
|
||||
QString getAcceptFunctionName(LookupScope *b, QString *retType) const
|
||||
QString getAcceptFunctionName(ClassOrNamespace *b, QString *retType) const
|
||||
{
|
||||
Q_ASSERT(b != 0);
|
||||
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
<< " Semantic(TranslationUnit *unit): ASTVisitor(unit) { translationUnit(unit->ast()->asTranslationUnit()); }" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
foreach (LookupScope *b, interfaces) {
|
||||
foreach (ClassOrNamespace *b, interfaces) {
|
||||
Q_ASSERT(! b->symbols().isEmpty());
|
||||
|
||||
Class *klass = 0;
|
||||
@@ -162,10 +162,10 @@ public:
|
||||
std::cout << " using ASTVisitor::translationUnit;" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
QHash<LookupScope *, QList<LookupScope *> > implements;
|
||||
foreach (LookupScope *b, nodes) {
|
||||
LookupScope *iface = 0;
|
||||
foreach (LookupScope *u, b->usings()) {
|
||||
QHash<ClassOrNamespace *, QList<ClassOrNamespace *> > implements;
|
||||
foreach (ClassOrNamespace *b, nodes) {
|
||||
ClassOrNamespace *iface = 0;
|
||||
foreach (ClassOrNamespace *u, b->usings()) {
|
||||
if (interfaces.contains(u)) {
|
||||
iface = u;
|
||||
break;
|
||||
@@ -175,8 +175,8 @@ public:
|
||||
implements[iface].append(b);
|
||||
}
|
||||
|
||||
foreach (LookupScope *iface, interfaces) {
|
||||
foreach (LookupScope *b, implements.value(iface)) {
|
||||
foreach (ClassOrNamespace *iface, interfaces) {
|
||||
foreach (ClassOrNamespace *b, implements.value(iface)) {
|
||||
if (! isMiscNode(b))
|
||||
continue;
|
||||
|
||||
@@ -195,9 +195,9 @@ public:
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
foreach (LookupScope *iface, interfaces) {
|
||||
foreach (ClassOrNamespace *iface, interfaces) {
|
||||
std::cout << " // " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
|
||||
foreach (LookupScope *b, implements.value(iface)) {
|
||||
foreach (ClassOrNamespace *b, implements.value(iface)) {
|
||||
Class *klass = 0;
|
||||
foreach (Symbol *s, b->symbols())
|
||||
if ((klass = s->asClass()) != 0)
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
}
|
||||
|
||||
std::cout << "private:" << std::endl;
|
||||
foreach (LookupScope *b, interfaces) {
|
||||
foreach (ClassOrNamespace *b, interfaces) {
|
||||
Q_ASSERT(! b->symbols().isEmpty());
|
||||
|
||||
Class *klass = 0;
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
|
||||
// implementation
|
||||
|
||||
foreach (LookupScope *b, interfaces) {
|
||||
foreach (ClassOrNamespace *b, interfaces) {
|
||||
Q_ASSERT(! b->symbols().isEmpty());
|
||||
|
||||
Class *klass = 0;
|
||||
@@ -280,9 +280,9 @@ public:
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
foreach (LookupScope *iface, interfaces) {
|
||||
foreach (ClassOrNamespace *iface, interfaces) {
|
||||
std::cout << "// " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
|
||||
foreach (LookupScope *b, implements.value(iface)) {
|
||||
foreach (ClassOrNamespace *b, implements.value(iface)) {
|
||||
Class *klass = 0;
|
||||
foreach (Symbol *s, b->symbols())
|
||||
if ((klass = s->asClass()) != 0)
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
Control *control = context.thisDocument()->control();
|
||||
const Name *n = control->identifier(name.toLatin1().constData());
|
||||
|
||||
if (LookupScope *bb = context.lookupType(n, klass)) {
|
||||
if (ClassOrNamespace *bb = context.lookupType(n, klass)) {
|
||||
QString retTy;
|
||||
QString funcName = getAcceptFunctionName(bb, &retTy);
|
||||
Q_ASSERT(! funcName.isEmpty());
|
||||
@@ -350,7 +350,7 @@ public:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (LookupScope *ty = context.lookupType(namedTy->name(), klass)) {
|
||||
if (ClassOrNamespace *ty = context.lookupType(namedTy->name(), klass)) {
|
||||
QString className = oo(ty->symbols().first()->name());
|
||||
QString baseClassName = className;
|
||||
if (baseClassName.endsWith(QLatin1String("AST"))) {
|
||||
@@ -386,9 +386,9 @@ public:
|
||||
protected:
|
||||
using SymbolVisitor::visit;
|
||||
|
||||
QList<LookupScope *> baseClasses(LookupScope *b) {
|
||||
QList<LookupScope *> usings = b->usings();
|
||||
foreach (LookupScope *u, usings)
|
||||
QList<ClassOrNamespace *> baseClasses(ClassOrNamespace *b) {
|
||||
QList<ClassOrNamespace *> usings = b->usings();
|
||||
foreach (ClassOrNamespace *u, usings)
|
||||
usings += baseClasses(u);
|
||||
return usings;
|
||||
}
|
||||
@@ -398,14 +398,14 @@ protected:
|
||||
if (! className.endsWith(QLatin1String("AST")))
|
||||
return false;
|
||||
|
||||
LookupScope *b = context.lookupType(klass);
|
||||
ClassOrNamespace *b = context.lookupType(klass);
|
||||
Q_ASSERT(b != 0);
|
||||
|
||||
const Identifier *accept0 = context.thisDocument()->control()->identifier("accept0");
|
||||
if (Symbol *s = klass->find(accept0)) {
|
||||
if (Function *meth = s->type()->asFunctionType()) {
|
||||
if (! meth->isPureVirtual()) {
|
||||
foreach (LookupScope *u, b->usings()) {
|
||||
foreach (ClassOrNamespace *u, b->usings()) {
|
||||
if (interfaces.contains(u)) {
|
||||
// qDebug() << oo(klass->name()) << "implements" << oo(u->symbols().first()->name());
|
||||
} else {
|
||||
|
@@ -115,7 +115,6 @@ public:
|
||||
|
||||
// Process source
|
||||
const Document::Ptr document = createDocument(filePath, source);
|
||||
QVERIFY(document);
|
||||
Snapshot snapshot;
|
||||
snapshot.insert(document);
|
||||
|
||||
@@ -225,8 +224,6 @@ private slots:
|
||||
void test_checksymbols_infiniteLoop_data();
|
||||
void test_checksymbols_infiniteLoop();
|
||||
|
||||
void test_checksymbols_infiniteLoop_BUG15141();
|
||||
|
||||
void test_parentOfBlock();
|
||||
|
||||
void findField();
|
||||
@@ -1173,25 +1170,6 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop()
|
||||
TestCase::runCheckSymbols(document1, snapshot);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_infiniteLoop_BUG15141()
|
||||
{
|
||||
QByteArray source =
|
||||
"template <class R1>\n"
|
||||
"struct Base\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename R>\n"
|
||||
"struct Derived :\n"
|
||||
" Base<\n"
|
||||
" typename Derived<typename Base<R>::type>::type,\n"
|
||||
" typename Derived<typename Base<R>::type>::type\n"
|
||||
" >::type\n"
|
||||
"{};\n";
|
||||
|
||||
BaseTestCase tc(source);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_parentOfBlock()
|
||||
{
|
||||
const QByteArray source = "void C::f()\n"
|
||||
@@ -1286,8 +1264,13 @@ void tst_CheckSymbols::findField()
|
||||
source[position] = ' ';
|
||||
BaseTestCase tc(source);
|
||||
Use use = tc.findUse(line, column);
|
||||
|
||||
QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("instantiation_of_pointer_typedef_in_block", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type_2", "QTCREATORBUG-14141", Abort);
|
||||
QVERIFY(use.isValid());
|
||||
QVERIFY(use.kind == Highlighting::FieldUse);
|
||||
}
|
||||
@@ -1364,26 +1347,6 @@ void tst_CheckSymbols::findField_data()
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("instantiation_of_indirect_typedef") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Indirect { _Tp t; };\n"
|
||||
"\n"
|
||||
"template<typename T>\n"
|
||||
"struct Temp\n"
|
||||
"{\n"
|
||||
" typedef T MyT;\n"
|
||||
" typedef Indirect<MyT> indirect;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" Temp<Foo>::indirect i;\n"
|
||||
" i.t.@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("pointer_indirect_specialization_double_indirection") << _(
|
||||
"template<typename _Tp>\n"
|
||||
"struct Traits { };\n"
|
||||
@@ -1475,100 +1438,6 @@ void tst_CheckSymbols::findField_data()
|
||||
" p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
QTest::newRow("std vector") << _(
|
||||
"namespace std\n"
|
||||
"{\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct allocator\n"
|
||||
"{\n"
|
||||
" typedef _Tp value_type;\n"
|
||||
"\n"
|
||||
" template<typename _Tp1>\n"
|
||||
" struct rebind\n"
|
||||
" { typedef allocator<_Tp1> other; };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Alloc, typename _Tp>\n"
|
||||
"struct __alloctr_rebind\n"
|
||||
"{\n"
|
||||
" typedef typename _Alloc::template rebind<_Tp>::other __type;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Alloc>\n"
|
||||
"struct allocator_traits\n"
|
||||
"{\n"
|
||||
" typedef typename _Alloc::value_type value_type;\n"
|
||||
"\n"
|
||||
" template<typename _Tp>\n"
|
||||
" using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Iterator>\n"
|
||||
"struct iterator_traits { };\n"
|
||||
"\n"
|
||||
"template<typename _Tp>\n"
|
||||
"struct iterator_traits<_Tp*>\n"
|
||||
"{\n"
|
||||
" typedef _Tp* pointer;\n"
|
||||
"};\n"
|
||||
"} // namespace std\n"
|
||||
"\n"
|
||||
"namespace __gnu_cxx\n"
|
||||
"{\n"
|
||||
"template<typename _Alloc>\n"
|
||||
"struct __alloc_traits\n"
|
||||
"{\n"
|
||||
" typedef _Alloc allocator_type;\n"
|
||||
" typedef std::allocator_traits<_Alloc> _Base_type;\n"
|
||||
" typedef typename _Alloc::value_type value_type;\n"
|
||||
"\n"
|
||||
" static value_type *_S_pointer_helper(...);\n"
|
||||
" typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n"
|
||||
" typedef __pointer pointer;\n"
|
||||
"\n"
|
||||
" template<typename _Tp>\n"
|
||||
" struct rebind\n"
|
||||
" { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Iterator, typename _Container>\n"
|
||||
"struct __normal_iterator\n"
|
||||
"{\n"
|
||||
" typedef std::iterator_traits<_Iterator> __traits_type;\n"
|
||||
" typedef typename __traits_type::pointer pointer;\n"
|
||||
"\n"
|
||||
" pointer p;\n"
|
||||
"};\n"
|
||||
"} // namespace __gnu_cxx\n"
|
||||
"\n"
|
||||
"namespace std {\n"
|
||||
"template<typename _Tp, typename _Alloc>\n"
|
||||
"struct _Vector_Base\n"
|
||||
"{\n"
|
||||
" typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n"
|
||||
" rebind<_Tp>::other _Tp_alloc_type;\n"
|
||||
" typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n"
|
||||
" pointer;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template<typename _Tp, typename _Alloc = std::allocator<_Tp> >\n"
|
||||
"struct vector : protected _Vector_Base<_Tp, _Alloc>\n"
|
||||
"{\n"
|
||||
" typedef _Vector_Base<_Tp, _Alloc> _Base;\n"
|
||||
" typedef typename _Base::pointer pointer;\n"
|
||||
" typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;\n"
|
||||
"};\n"
|
||||
"} // namespace std\n"
|
||||
"\n"
|
||||
"struct Foo { int bar; };\n"
|
||||
"\n"
|
||||
"void func()\n"
|
||||
"{\n"
|
||||
" std::vector<Foo>::iterator it;\n"
|
||||
" it.p->@bar;\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
||||
|
@@ -133,7 +133,7 @@ void tst_Lookup::base_class_defined_1()
|
||||
|
||||
const LookupContext ctx(doc, snapshot);
|
||||
|
||||
LookupScope *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope());
|
||||
ClassOrNamespace *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope());
|
||||
QVERIFY(klass != 0);
|
||||
|
||||
QCOMPARE(klass->symbols().size(), 1);
|
||||
@@ -272,7 +272,7 @@ void tst_Lookup::simple_class_1()
|
||||
const LookupContext context(doc, snapshot);
|
||||
|
||||
// check class resolving:
|
||||
LookupScope *klass = context.lookupType(impl->name(), impl->enclosingScope());
|
||||
ClassOrNamespace *klass = context.lookupType(impl->name(), impl->enclosingScope());
|
||||
QVERIFY(klass != 0);
|
||||
QCOMPARE(klass->symbols().size(), 2);
|
||||
QVERIFY(klass->symbols().contains(iface));
|
||||
@@ -336,7 +336,7 @@ void tst_Lookup::class_with_baseclass()
|
||||
|
||||
const LookupContext context(doc, snapshot);
|
||||
|
||||
LookupScope *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope());
|
||||
ClassOrNamespace *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope());
|
||||
QVERIFY(objClass != 0);
|
||||
QVERIFY(objClass->symbols().contains(baseZoo));
|
||||
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include <cplusplus/Bind.h>
|
||||
#include <cplusplus/Control.h>
|
||||
#include <cplusplus/CoreTypes.h>
|
||||
#include <cplusplus/DeprecatedGenTemplateInstance.h>
|
||||
#include <cplusplus/DiagnosticClient.h>
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <cplusplus/Literals.h>
|
||||
@@ -47,7 +48,6 @@
|
||||
#include <cplusplus/Parser.h>
|
||||
#include <cplusplus/Scope.h>
|
||||
#include <cplusplus/Symbols.h>
|
||||
#include <cplusplus/Templates.h>
|
||||
|
||||
//TESTED_COMPONENT=src/libs/cplusplus
|
||||
|
||||
@@ -166,7 +166,6 @@ private slots:
|
||||
void pointer_to_function_1();
|
||||
|
||||
void template_instance_1();
|
||||
void explicit_instantiation_1();
|
||||
|
||||
void expression_under_cursor_1();
|
||||
|
||||
@@ -512,37 +511,17 @@ void tst_Semantic::template_instance_1()
|
||||
QVERIFY(decl);
|
||||
|
||||
FullySpecifiedType templArgs[] = { control->integerType(IntegerType::Int) };
|
||||
Clone cloner(control.data());
|
||||
Class *clone = cloner.instantiate(templ, templArgs, 1)->asClass();
|
||||
QVERIFY(clone);
|
||||
const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1);
|
||||
|
||||
FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control);
|
||||
|
||||
Overview oo;
|
||||
oo.showReturnTypes = true;
|
||||
|
||||
Declaration *clonedDecl = clone->memberAt(0)->asDeclaration();
|
||||
const QString genDecl = oo.prettyType(clonedDecl->type());
|
||||
const QString genDecl = oo.prettyType(genTy);
|
||||
QCOMPARE(genDecl, QString::fromLatin1("void (const int &)"));
|
||||
}
|
||||
|
||||
void tst_Semantic::explicit_instantiation_1()
|
||||
{
|
||||
QSharedPointer<Document> doc = document("template class basic_string<char>;");
|
||||
QCOMPARE(doc->errorCount, 0U);
|
||||
QCOMPARE(doc->globals->memberCount(), 1U);
|
||||
|
||||
ExplicitInstantiation *inst = doc->globals->memberAt(0)->asExplicitInstantiation();
|
||||
QVERIFY(inst);
|
||||
|
||||
ForwardClassDeclaration *fwd = inst->memberAt(0)->asForwardClassDeclaration();
|
||||
QVERIFY(fwd);
|
||||
|
||||
QVERIFY(inst->name()->match(fwd->name()));
|
||||
|
||||
Overview oo;
|
||||
const QString name = oo.prettyName(inst->name());
|
||||
QCOMPARE(name, QString::fromLatin1("basic_string<char>"));
|
||||
}
|
||||
|
||||
void tst_Semantic::expression_under_cursor_1()
|
||||
{
|
||||
const QString plainText = "void *ptr = foo(10, bar";
|
||||
|
Reference in New Issue
Block a user