Commit bb263645 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Improved the resolving of member expressions.

parent cae8a31a
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment