forked from qt-creator/qt-creator
C++: Better resolution for typedef when resolving expr.
Example: struct Bar { int m; }; typedef Bar *pBar; pBar b; b-> // completes correctly now Change-Id: I97cc67579b955fe47c68ab6c35be9a054b6d1be9 Done-by: ckamm Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
@@ -485,8 +485,6 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
|||||||
const TemplateNameId *templateId,
|
const TemplateNameId *templateId,
|
||||||
ClassOrNamespace *binding)
|
ClassOrNamespace *binding)
|
||||||
{
|
{
|
||||||
Q_UNUSED(templateId);
|
|
||||||
|
|
||||||
if (! name) {
|
if (! name) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtCore/QtDebug>
|
#include <QtCore/QtDebug>
|
||||||
|
#include <QtCore/QSet>
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
@@ -679,6 +680,38 @@ ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &origina
|
|||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resolveTypedefs(const LookupContext &context,
|
||||||
|
FullySpecifiedType *type,
|
||||||
|
Scope **scope)
|
||||||
|
{
|
||||||
|
QSet<Symbol *> visited;
|
||||||
|
while (NamedType *namedTy = (*type)->asNamedType()) {
|
||||||
|
ClassOrNamespace *scopeCoN = context.lookupType(*scope);
|
||||||
|
if (!scopeCoN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// check if namedTy->name() resolves to a typedef
|
||||||
|
QList<LookupItem> namedTypeItems = scopeCoN->lookup(namedTy->name());
|
||||||
|
bool foundTypedef = false;
|
||||||
|
foreach (const LookupItem &it, namedTypeItems) {
|
||||||
|
if (it.declaration() && it.declaration()->isTypedef()) {
|
||||||
|
if (visited.contains(it.declaration()))
|
||||||
|
break;
|
||||||
|
visited.insert(it.declaration());
|
||||||
|
|
||||||
|
// continue working with the typedefed type and scope
|
||||||
|
*type = it.declaration()->type();
|
||||||
|
*scope = it.scope();
|
||||||
|
foundTypedef = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundTypedef)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
|
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
|
||||||
int accessOp,
|
int accessOp,
|
||||||
bool *replacedDotOperator) const
|
bool *replacedDotOperator) const
|
||||||
@@ -687,6 +720,8 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
|||||||
FullySpecifiedType ty = r.type().simplified();
|
FullySpecifiedType ty = r.type().simplified();
|
||||||
Scope *scope = r.scope();
|
Scope *scope = r.scope();
|
||||||
|
|
||||||
|
resolveTypedefs(_context, &ty, &scope);
|
||||||
|
|
||||||
if (accessOp == T_ARROW) {
|
if (accessOp == T_ARROW) {
|
||||||
if (PointerType *ptrTy = ty->asPointerType()) {
|
if (PointerType *ptrTy = ty->asPointerType()) {
|
||||||
if (ClassOrNamespace *binding = findClass(ptrTy->elementType(), scope))
|
if (ClassOrNamespace *binding = findClass(ptrTy->elementType(), scope))
|
||||||
@@ -700,6 +735,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
|||||||
Symbol *overload = r.declaration();
|
Symbol *overload = r.declaration();
|
||||||
if (! overload)
|
if (! overload)
|
||||||
continue;
|
continue;
|
||||||
|
Scope *functionScope = overload->enclosingScope();
|
||||||
|
|
||||||
if (overload->type()->isFunctionType()) {
|
if (overload->type()->isFunctionType()) {
|
||||||
FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
|
FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
|
||||||
@@ -708,11 +744,13 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
|||||||
|
|
||||||
FullySpecifiedType retTy = instantiatedFunction->returnType().simplified();
|
FullySpecifiedType retTy = instantiatedFunction->returnType().simplified();
|
||||||
|
|
||||||
|
resolveTypedefs(_context, &retTy, &functionScope);
|
||||||
|
|
||||||
if (PointerType *ptrTy = retTy->asPointerType()) {
|
if (PointerType *ptrTy = retTy->asPointerType()) {
|
||||||
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), overload->enclosingScope()))
|
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), functionScope))
|
||||||
return retBinding;
|
return retBinding;
|
||||||
|
|
||||||
if (scope != overload->enclosingScope()) {
|
if (scope != functionScope) {
|
||||||
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
|
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
|
||||||
return retBinding;
|
return retBinding;
|
||||||
}
|
}
|
||||||
@@ -720,7 +758,7 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
|||||||
if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
|
if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
|
||||||
foreach (Symbol *originSymbol, origin->symbols()) {
|
foreach (Symbol *originSymbol, origin->symbols()) {
|
||||||
Scope *originScope = originSymbol->asScope();
|
Scope *originScope = originSymbol->asScope();
|
||||||
if (originScope && originScope != scope && originScope != overload->enclosingScope()) {
|
if (originScope && originScope != scope && originScope != functionScope) {
|
||||||
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope))
|
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope))
|
||||||
return retBinding;
|
return retBinding;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user