diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 83082853176b5c917ea8a5cd26b1b247e56ce588..31ff8a00865e3fe28fab0bb526b0bb35180d4db8 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::Result> -ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults, - unsigned accessOp, - Name *memberName) const +QList<Symbol *> ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const { - ResolveClass resolveClass; - QList<Result> results; + QList<Symbol *> classObjectCandidates; - if (accessOp == T_ARROW) { - foreach (Result p, baseResults) { - FullySpecifiedType ty = p.first; + if (baseResults.isEmpty()) + return classObjectCandidates; - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); + Result result = baseResults.first(); - if (NamedType *namedTy = ty->asNamedType()) { - resolveClass.setPointerAccess(true); - QList<Symbol *> classObjectCandidates = resolveClass(namedTy, p, _context); + if (accessOp == T_ARROW) { + FullySpecifiedType ty = result.first.simplified(); - foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, - control()->namedType(classObject->name()), // ### remove the call to namedType - classObject->asClass()); + 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<Symbol *> 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; - if (classObjectCandidates.isEmpty()) { - resolveClass.setPointerAccess(false); - classObjectCandidates = resolveClass(namedTy, p, _context); + const QList<Symbol *> candidates = resolveClass(result, _context); + foreach (Symbol *classObject, candidates) { + const QList<Result> overloads = resolveArrowOperator(result, namedTy, + classObject->asClass()); - foreach (Symbol *classObject, classObjectCandidates) { - const QList<Result> overloads = resolveArrowOperator(p, namedTy, - classObject->asClass()); - foreach (Result r, overloads) { - FullySpecifiedType ty = r.first; - Function *funTy = ty->asFunctionType(); - if (! funTy) - continue; + foreach (Result r, overloads) { + FullySpecifiedType ty = r.first; + Function *funTy = ty->asFunctionType(); + if (! funTy) + continue; - ty = funTy->returnType(); + ty = funTy->returnType().simplified(); - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); + if (PointerType *ptrTy = ty->asPointerType()) { + if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { + const QList<Symbol *> classes = + resolveClass(namedTy, result, _context); - if (PointerType *ptrTy = ty->asPointerType()) { - if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) - results += resolveMember(r, memberName, namedTy); + foreach (Symbol *c, classes) { + if (! classObjectCandidates.contains(c)) + classObjectCandidates.append(c); } } } } - } 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; + } else if (PointerType *ptrTy = ty->asPointerType()) { + if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { + ResolveClass resolveClass; - if (ReferenceType *refTy = ty->asReferenceType()) - ty = refTy->elementType(); + const QList<Symbol *> classes = resolveClass(namedTy, result, + _context); - 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); + 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<Symbol *> symbols = resolveClass(namedTy, result, + _context); + foreach (Symbol *symbol, symbols) { + if (classObjectCandidates.contains(symbol)) + continue; + if (Class *klass = symbol->asClass()) + classObjectCandidates.append(klass); + } } } - return results; + return classObjectCandidates; } QList<ResolveExpression::Result> -ResolveExpression::resolveMember(const Result &p, - Name *memberName, - NamedType *namedTy) const +ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults, + unsigned accessOp, + Name *memberName) const { - ResolveClass resolveClass; + QList<Result> results; - const QList<Symbol *> classObjectCandidates = - resolveClass(namedTy, p, _context); + const QList<Symbol *> classObjectCandidates = resolveBaseExpression(baseResults, accessOp); + foreach (Symbol *candidate, classObjectCandidates) { + Class *klass = candidate->asClass(); + if (! klass) + continue; - QList<Result> results; - foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, namedTy, - classObject->asClass()); + results += resolveMember(memberName, klass); } + return results; } QList<ResolveExpression::Result> -ResolveExpression::resolveMember(const Result &, - Name *memberName, - NamedType *namedTy, - Class *klass) const +ResolveExpression::resolveMember(Name *memberName, Class *klass) const { + QList<Result> results; + QList<Scope *> scopes; _context.expand(klass->members(), _context.visibleScopes(), &scopes); - QList<Result> results; QList<Symbol *> 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 f548e9a15c5f976f5886c088200a5ce661876f84..71289ef34320fec21ff59e56867daa8ff9a1d106 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -53,14 +53,7 @@ public: unsigned accessOp, Name *memberName) const; - QList<Result> resolveMember(const Result &result, - Name *memberName, - NamedType *namedTy) const; - - QList<Result> resolveMember(const Result &result, - Name *memberName, - NamedType *namedTy, - Class *klass) const; + QList<Result> resolveMember(Name *memberName, Class *klass) const; QList<Result> resolveArrowOperator(const Result &result, NamedType *namedTy, @@ -70,6 +63,10 @@ public: NamedType *namedTy, Class *klass) const; + + QList<Symbol *> resolveBaseExpression(const QList<Result> &baseResults, + int accessOp) const; + protected: QList<Result> switchResults(const QList<Result> &symbols);