diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 83082853176..31ff8a00865 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -623,141 +623,175 @@ bool ResolveExpression::visit(MemberAccessAST *ast) memberName = ast->member_name->name; // Remember the access operator. - const unsigned accessOp = tokenKind(ast->access_token); + const int accessOp = tokenKind(ast->access_token); _results = resolveMemberExpression(baseResults, accessOp, memberName); return false; } +QList ResolveExpression::resolveBaseExpression(const QList &baseResults, int accessOp) const +{ + QList classObjectCandidates; + + if (baseResults.isEmpty()) + return classObjectCandidates; + + Result result = baseResults.first(); + + if (accessOp == T_ARROW) { + FullySpecifiedType ty = result.first.simplified(); + + if (Class *classTy = ty->asClassType()) { + Symbol *symbol = result.second; + if (symbol && ! symbol->isClass()) + classObjectCandidates.append(classTy); + } else if (NamedType *namedTy = ty->asNamedType()) { + // ### This code is pretty slow. + const QList candidates = _context.resolve(namedTy->name()); + foreach (Symbol *candidate, candidates) { + if (candidate->isTypedef()) { + ty = candidate->type(); + const ResolveExpression::Result r(ty, candidate); + result = r; + break; + } + } + } + + if (NamedType *namedTy = ty->asNamedType()) { + ResolveClass resolveClass; + + const QList candidates = resolveClass(result, _context); + foreach (Symbol *classObject, candidates) { + const QList overloads = resolveArrowOperator(result, namedTy, + classObject->asClass()); + + foreach (Result r, overloads) { + FullySpecifiedType ty = r.first; + Function *funTy = ty->asFunctionType(); + if (! funTy) + continue; + + ty = funTy->returnType().simplified(); + + if (PointerType *ptrTy = ty->asPointerType()) { + if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { + const QList classes = + resolveClass(namedTy, result, _context); + + foreach (Symbol *c, classes) { + if (! classObjectCandidates.contains(c)) + classObjectCandidates.append(c); + } + } + } + } + } + } else if (PointerType *ptrTy = ty->asPointerType()) { + if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { + ResolveClass resolveClass; + + const QList classes = resolveClass(namedTy, result, + _context); + + foreach (Symbol *c, classes) { + if (! classObjectCandidates.contains(c)) + classObjectCandidates.append(c); + } + } else if (Class *classTy = ptrTy->elementType()->asClassType()) { + // typedef struct { int x } *Ptr; + // Ptr p; + // p-> + classObjectCandidates.append(classTy); + } + } + } else if (accessOp == T_DOT) { + FullySpecifiedType ty = result.first.simplified(); + + NamedType *namedTy = 0; + + if (Class *classTy = ty->asClassType()) { + Symbol *symbol = result.second; + if (symbol && ! symbol->isClass()) + classObjectCandidates.append(classTy); + } else { + namedTy = ty->asNamedType(); + if (! namedTy) { + Function *fun = ty->asFunctionType(); + if (fun && fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope())) + namedTy = fun->returnType()->asNamedType(); + } + } + + if (namedTy) { + ResolveClass resolveClass; + const QList symbols = resolveClass(namedTy, result, + _context); + foreach (Symbol *symbol, symbols) { + if (classObjectCandidates.contains(symbol)) + continue; + if (Class *klass = symbol->asClass()) + classObjectCandidates.append(klass); + } + } + } + + return classObjectCandidates; +} + QList ResolveExpression::resolveMemberExpression(const QList &baseResults, unsigned accessOp, Name *memberName) const { - ResolveClass resolveClass; QList results; - if (accessOp == T_ARROW) { - foreach (Result p, baseResults) { - FullySpecifiedType ty = p.first; + const QList classObjectCandidates = resolveBaseExpression(baseResults, accessOp); + foreach (Symbol *candidate, classObjectCandidates) { + Class *klass = candidate->asClass(); + if (! klass) + continue; - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); - - if (NamedType *namedTy = ty->asNamedType()) { - resolveClass.setPointerAccess(true); - QList classObjectCandidates = resolveClass(namedTy, p, _context); - - foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, - control()->namedType(classObject->name()), // ### remove the call to namedType - classObject->asClass()); - } - - if (classObjectCandidates.isEmpty()) { - resolveClass.setPointerAccess(false); - classObjectCandidates = resolveClass(namedTy, p, _context); - - foreach (Symbol *classObject, classObjectCandidates) { - const QList overloads = resolveArrowOperator(p, namedTy, - classObject->asClass()); - foreach (Result r, overloads) { - FullySpecifiedType ty = r.first; - Function *funTy = ty->asFunctionType(); - if (! funTy) - continue; - - ty = funTy->returnType(); - - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); - - if (PointerType *ptrTy = ty->asPointerType()) { - if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) - results += resolveMember(r, memberName, namedTy); - } - } - } - } - } else if (PointerType *ptrTy = ty->asPointerType()) { - if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) - results += resolveMember(p, memberName, namedTy); - } - } - } else if (accessOp == T_DOT) { - // The base expression shall be a "class object" of a complete type. - foreach (Result p, baseResults) { - FullySpecifiedType ty = p.first; - - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); - - if (NamedType *namedTy = ty->asNamedType()) - results += resolveMember(p, memberName, namedTy); - else if (Function *fun = ty->asFunctionType()) { - if (fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope())) { - ty = fun->returnType(); - - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); - - if (NamedType *namedTy = ty->asNamedType()) - results += resolveMember(p, memberName, namedTy); - } - } - - } + results += resolveMember(memberName, klass); } return results; } QList -ResolveExpression::resolveMember(const Result &p, - Name *memberName, - NamedType *namedTy) const +ResolveExpression::resolveMember(Name *memberName, Class *klass) const { - ResolveClass resolveClass; - - const QList classObjectCandidates = - resolveClass(namedTy, p, _context); - QList results; - foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, namedTy, - classObject->asClass()); - } - return results; -} -QList -ResolveExpression::resolveMember(const Result &, - Name *memberName, - NamedType *namedTy, - Class *klass) const -{ QList scopes; _context.expand(klass->members(), _context.visibleScopes(), &scopes); - QList results; QList candidates = _context.resolve(memberName, scopes); + foreach (Symbol *candidate, candidates) { FullySpecifiedType ty = candidate->type(); - Name *unqualifiedNameId = namedTy->name(); - if (QualifiedNameId *q = namedTy->name()->asQualifiedNameId()) - unqualifiedNameId = q->unqualifiedNameId(); - if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { - Substitution subst; - for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { - FullySpecifiedType templArgTy = templId->templateArgumentAt(i); - if (i < klass->templateParameterCount()) { - subst.append(qMakePair(klass->templateParameterAt(i)->name(), - templArgTy)); + + if (Name *className = klass->name()) { + Name *unqualifiedNameId = className; + + if (QualifiedNameId *q = className->asQualifiedNameId()) + unqualifiedNameId = q->unqualifiedNameId(); + + if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { + Substitution subst; + + for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { + FullySpecifiedType templArgTy = templId->templateArgumentAt(i); + + if (i < klass->templateParameterCount()) + subst.append(qMakePair(klass->templateParameterAt(i)->name(), + templArgTy)); } + + Instantiation inst(control(), subst); + ty = inst(ty); } - Instantiation inst(control(), subst); - ty = inst(ty); } const Result result(ty, candidate); diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index f548e9a15c5..71289ef3432 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -53,14 +53,7 @@ public: unsigned accessOp, Name *memberName) const; - QList resolveMember(const Result &result, - Name *memberName, - NamedType *namedTy) const; - - QList resolveMember(const Result &result, - Name *memberName, - NamedType *namedTy, - Class *klass) const; + QList resolveMember(Name *memberName, Class *klass) const; QList resolveArrowOperator(const Result &result, NamedType *namedTy, @@ -70,6 +63,10 @@ public: NamedType *namedTy, Class *klass) const; + + QList resolveBaseExpression(const QList &baseResults, + int accessOp) const; + protected: QList switchResults(const QList &symbols);