ResolveExpression.cpp 31 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12
13
14
15
16
17
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21
22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23
24
25
26
27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
**
29
**************************************************************************/
con's avatar
con committed
30
31

#include "ResolveExpression.h"
32
#include "LookupContext.h"
con's avatar
con committed
33
#include "Overview.h"
34
#include "DeprecatedGenTemplateInstance.h"
35
#include "CppRewriter.h"
36
#include "TypeOfExpression.h"
con's avatar
con committed
37
38
39
40
41
42
43
44
45
46

#include <Control.h>
#include <AST.h>
#include <Scope.h>
#include <Names.h>
#include <Symbols.h>
#include <Literals.h>
#include <CoreTypes.h>
#include <TypeVisitor.h>
#include <NameVisitor.h>
47
#include <Templates.h>
hjk's avatar
hjk committed
48

49
#include <QList>
hjk's avatar
hjk committed
50
#include <QDebug>
51
#include <QSet>
52
#include <map>
con's avatar
con committed
53
54
55

using namespace CPlusPlus;

hjk's avatar
hjk committed
56
namespace {
con's avatar
con committed
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
template <typename _Tp>
static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
{
    QList<_Tp> uniqueList;
    QSet<_Tp> processed;
    foreach (const _Tp &r, results) {
        if (processed.contains(r))
            continue;

        processed.insert(r);
        uniqueList.append(r);
    }

    return uniqueList;
}

con's avatar
con committed
74
75
76
77
78
} // end of anonymous namespace

/////////////////////////////////////////////////////////////////////
// ResolveExpression
/////////////////////////////////////////////////////////////////////
79
ResolveExpression::ResolveExpression(const LookupContext &context)
Roberto Raggi's avatar
Roberto Raggi committed
80
    : ASTVisitor(context.expressionDocument()->translationUnit()),
81
      _scope(0),
con's avatar
con committed
82
      _context(context),
83
84
      bind(context.expressionDocument()->translationUnit()),
      _reference(false)
85
{ }
con's avatar
con committed
86
87
88
89

ResolveExpression::~ResolveExpression()
{ }

90
91
92
QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope)
{ return resolve(ast, scope); }

93
94
95
96
QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope)
{ return resolve(ast, scope, true); }

QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref)
97
{
Roberto Raggi's avatar
Roberto Raggi committed
98
99
    if (! scope)
        return QList<LookupItem>();
100

101
102
103
104
105
106
107
108
    std::swap(_scope, scope);
    std::swap(_reference, ref);

    const QList<LookupItem> result = expression(ast);

    std::swap(_reference, ref);
    std::swap(_scope, scope);

109
110
111
    return result;
}

112
QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast)
con's avatar
con committed
113
{
114
    const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
con's avatar
con committed
115
    accept(ast);
116
    return removeDuplicates(switchResults(previousResults));
con's avatar
con committed
117
118
}

119
QList<LookupItem> ResolveExpression::switchResults(const QList<LookupItem> &results)
con's avatar
con committed
120
{
121
    const QList<LookupItem> previousResults = _results;
con's avatar
con committed
122
123
124
125
    _results = results;
    return previousResults;
}

126
void ResolveExpression::addResults(const QList<Symbol *> &symbols)
con's avatar
con committed
127
{
128
129
130
    foreach (Symbol *symbol, symbols) {
        LookupItem item;
        item.setType(symbol->type());
131
        item.setScope(symbol->enclosingScope());
132
        item.setDeclaration(symbol);
133
134
        _results.append(item);
    }
con's avatar
con committed
135
136
}

137
138
139
140
141
void ResolveExpression::addResults(const QList<LookupItem> &items)
{
    _results += items;
}

142
void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope)
con's avatar
con committed
143
{
144
145
146
    LookupItem item;
    item.setType(ty);
    item.setScope(scope);
con's avatar
con committed
147

148
    _results.append(item);
149
}
con's avatar
con committed
150

Roberto Raggi's avatar
Roberto Raggi committed
151
152
153
154
155
156
bool ResolveExpression::visit(IdExpressionAST *ast)
{
    accept(ast->name);
    return false;
}

157
bool ResolveExpression::visit(BinaryExpressionAST *ast)
con's avatar
con committed
158
{
159
160
161
162
163
164
165
166
167
168
    if (tokenKind(ast->binary_op_token) == T_COMMA && ast->right_expression && ast->right_expression->asQtMethod() != 0) {

        if (ast->left_expression && ast->left_expression->asQtMethod() != 0)
            thisObject();
        else
            accept(ast->left_expression);

        QtMethodAST *qtMethod = ast->right_expression->asQtMethod();
        if (DeclaratorAST *d = qtMethod->declarator) {
            if (d->core_declarator) {
169
170
171
172
173
174
175
176
                if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) {
                    if (NameAST *nameAST = declaratorId->name) {
                        if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) {
                            _results.clear();
                            addResults(binding->lookup(nameAST->name));
                        }
                    }
                }
177
178
179
180
181
182
            }
        }

        return false;
    }

183
    accept(ast->left_expression);
con's avatar
con committed
184
185
186
187
188
    return false;
}

bool ResolveExpression::visit(CastExpressionAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
189
    Scope *dummyScope = _context.expressionDocument()->globalNamespace();
190
    FullySpecifiedType ty = bind(ast->type_id, dummyScope);
191
    addResult(ty, _scope);
con's avatar
con committed
192
193
194
195
196
197
198
199
200
    return false;
}

bool ResolveExpression::visit(ConditionAST *)
{
    // nothing to do.
    return false;
}

201
bool ResolveExpression::visit(ConditionalExpressionAST *ast)
con's avatar
con committed
202
{
203
204
205
206
207
208
    if (ast->left_expression)
        accept(ast->left_expression);

    else if (ast->right_expression)
        accept(ast->right_expression);

con's avatar
con committed
209
210
211
212
213
    return false;
}

bool ResolveExpression::visit(CppCastExpressionAST *ast)
{
Roberto Raggi's avatar
Roberto Raggi committed
214
    Scope *dummyScope = _context.expressionDocument()->globalNamespace();
215
    FullySpecifiedType ty = bind(ast->type_id, dummyScope);
216
    addResult(ty, _scope);
con's avatar
con committed
217
218
219
220
221
    return false;
}

bool ResolveExpression::visit(DeleteExpressionAST *)
{
222
    FullySpecifiedType ty(control()->voidType());
223
    addResult(ty, _scope);
con's avatar
con committed
224
225
226
227
228
229
230
231
232
    return false;
}

bool ResolveExpression::visit(ArrayInitializerAST *)
{
    // nothing to do.
    return false;
}

233
bool ResolveExpression::visit(NewExpressionAST *ast)
con's avatar
con committed
234
{
235
    if (ast->new_type_id) {
Roberto Raggi's avatar
Roberto Raggi committed
236
        Scope *dummyScope = _context.expressionDocument()->globalNamespace();
237
        FullySpecifiedType ty = bind(ast->new_type_id, dummyScope);
238
        FullySpecifiedType ptrTy(control()->pointerType(ty));
239
        addResult(ptrTy, _scope);
240
    }
con's avatar
con committed
241
242
243
244
245
246
    // nothing to do.
    return false;
}

bool ResolveExpression::visit(TypeidExpressionAST *)
{
247
248
    const Name *stdName = control()->identifier("std");
    const Name *tiName = control()->identifier("type_info");
249
    const Name *q = control()->qualifiedNameId(control()->qualifiedNameId(/* :: */ 0, stdName), tiName);
con's avatar
con committed
250
251

    FullySpecifiedType ty(control()->namedType(q));
252
    addResult(ty, _scope);
con's avatar
con committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

    return false;
}

bool ResolveExpression::visit(TypenameCallExpressionAST *)
{
    // nothing to do
    return false;
}

bool ResolveExpression::visit(TypeConstructorCallAST *)
{
    // nothing to do.
    return false;
}

bool ResolveExpression::visit(SizeofExpressionAST *)
{
    FullySpecifiedType ty(control()->integerType(IntegerType::Int));
    ty.setUnsigned(true);
273
    addResult(ty, _scope);
con's avatar
con committed
274
275
276
    return false;
}

Leandro Melo's avatar
Leandro Melo committed
277
278
279
280
281
282
283
bool ResolveExpression::visit(PointerLiteralAST *)
{
    FullySpecifiedType ty(control()->integerType(IntegerType::Int)); // Handling as Int.
    addResult(ty, _scope);
    return false;
}

284
bool ResolveExpression::visit(NumericLiteralAST *ast)
con's avatar
con committed
285
{
286
287
    const Token &tk = tokenAt(ast->literal_token);

288
    Type *type = 0;
289
    bool isUnsigned = false;
290

291
    if (tk.is(T_CHAR_LITERAL)) {
292
        type = control()->integerType(IntegerType::Char);
293
    } else if (tk.is(T_WIDE_CHAR_LITERAL)) {
294
        type = control()->integerType(IntegerType::WideChar);
295
296
297
298
299
    } else if (tk.is(T_UTF16_CHAR_LITERAL)) {
        type = control()->integerType(IntegerType::Char16);
    } else if (tk.is(T_UTF32_CHAR_LITERAL)) {
        type = control()->integerType(IntegerType::Char32);
    } else if (const NumericLiteral *literal = numericLiteral(ast->literal_token)) {
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
        isUnsigned = literal->isUnsigned();
        if (literal->isInt())
            type = control()->integerType(IntegerType::Int);
        else if (literal->isLong())
            type = control()->integerType(IntegerType::Long);
        else if (literal->isLongLong())
            type = control()->integerType(IntegerType::LongLong);
        else if (literal->isFloat())
            type = control()->floatType(FloatType::Float);
        else if (literal->isDouble())
            type = control()->floatType(FloatType::Double);
        else if (literal->isLongDouble())
            type = control()->floatType(FloatType::LongDouble);
        else
            type = control()->integerType(IntegerType::Int);
    }
316
317

    FullySpecifiedType ty(type);
318
    ty.setUnsigned(isUnsigned);
319
    addResult(ty, _scope);
con's avatar
con committed
320
321
322
323
324
325
    return false;
}

bool ResolveExpression::visit(BoolLiteralAST *)
{
    FullySpecifiedType ty(control()->integerType(IntegerType::Bool));
326
    addResult(ty, _scope);
con's avatar
con committed
327
328
329
330
    return false;
}

bool ResolveExpression::visit(ThisExpressionAST *)
331
332
333
334
335
336
{
    thisObject();
    return false;
}

void ResolveExpression::thisObject()
con's avatar
con committed
337
{
338
    Scope *scope = _scope;
339
    for (; scope; scope = scope->enclosingScope()) {
Roberto Raggi's avatar
Roberto Raggi committed
340
341
        if (Function *fun = scope->asFunction()) {
            if (Class *klass = scope->enclosingClass()) {
con's avatar
con committed
342
343
                FullySpecifiedType classTy(control()->namedType(klass->name()));
                FullySpecifiedType ptrTy(control()->pointerType(classTy));
344
                addResult(ptrTy, fun->enclosingScope());
con's avatar
con committed
345
                break;
Roberto Raggi's avatar
Roberto Raggi committed
346
            } else if (const QualifiedNameId *q = fun->name()->asQualifiedNameId()) {
347
348
349
                if (q->base()) {
                    FullySpecifiedType classTy(control()->namedType(q->base()));
                    FullySpecifiedType ptrTy(control()->pointerType(classTy));
350
                    addResult(ptrTy, fun->enclosingScope());
351
                }
con's avatar
con committed
352
353
354
355
356
357
                break;
            }
        }
    }
}

358
359
bool ResolveExpression::visit(CompoundExpressionAST *ast)
{
360
    CompoundStatementAST *cStmt = ast->statement;
361
362
363
364
    if (cStmt && cStmt->statement_list) {
        accept(cStmt->statement_list->lastValue());
    }
    return false;
365
366
}

con's avatar
con committed
367
368
369
370
371
372
373
374
375
376
377
bool ResolveExpression::visit(NestedExpressionAST *ast)
{
    accept(ast->expression);
    return false;
}

bool ResolveExpression::visit(StringLiteralAST *)
{
    FullySpecifiedType charTy = control()->integerType(IntegerType::Char);
    charTy.setConst(true);
    FullySpecifiedType ty(control()->pointerType(charTy));
378
    addResult(ty, _scope);
con's avatar
con committed
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    return false;
}

bool ResolveExpression::visit(ThrowExpressionAST *)
{
    return false;
}

bool ResolveExpression::visit(TypeIdAST *)
{
    return false;
}

bool ResolveExpression::visit(UnaryExpressionAST *ast)
{
    accept(ast->expression);
    unsigned unaryOp = tokenKind(ast->unary_op_token);
    if (unaryOp == T_AMPER) {
397
        QMutableListIterator<LookupItem > it(_results);
con's avatar
con committed
398
        while (it.hasNext()) {
399
400
401
402
            LookupItem p = it.next();
            FullySpecifiedType ty = p.type();
            ty.setType(control()->pointerType(ty));
            p.setType(ty);
con's avatar
con committed
403
404
405
            it.setValue(p);
        }
    } else if (unaryOp == T_STAR) {
406
        QMutableListIterator<LookupItem > it(_results);
con's avatar
con committed
407
        while (it.hasNext()) {
408
            LookupItem p = it.next();
409
410
411
412
413
414
415
416
417
            FullySpecifiedType ty = p.type();
            NamedType *namedTy = ty->asNamedType();
            if (namedTy != 0) {
                const QList<LookupItem> types = _context.lookup(namedTy->name(), p.scope());
                if (!types.empty())
                    ty = types.front().type();
            }
            bool added = false;
            if (PointerType *ptrTy = ty->asPointerType()) {
418
                p.setType(ptrTy->elementType());
con's avatar
con committed
419
                it.setValue(p);
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
                added = true;
            } else if (namedTy != 0) {
                const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp);
                if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), p.scope())) {
                    foreach (const LookupItem &r, b->find(starOp)) {
                        Symbol *overload = r.declaration();
                        if (Function *funTy = overload->type()->asFunctionType()) {
                            if (maybeValidPrototype(funTy, 0)) {
                                if (Function *proto = instantiate(b->templateId(), funTy)->asFunctionType()) {
                                    FullySpecifiedType retTy = proto->returnType().simplified();
                                    p.setType(retTy);
                                    p.setScope(proto->enclosingScope());
                                    it.setValue(p);
                                    added = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (!added)
                    it.remove();
con's avatar
con committed
442
443
444
445
446
447
            }
        }
    }
    return false;
}

448
449
450
451
452
453
bool ResolveExpression::visit(CompoundLiteralAST *ast)
{
    accept(ast->type_id);
    return false;
}

con's avatar
con committed
454
455
bool ResolveExpression::visit(QualifiedNameAST *ast)
{
456
    if (const Name *name = ast->name) {
457
        const QList<LookupItem> candidates = _context.lookup(name, _scope);
458
        addResults(candidates);
con's avatar
con committed
459
460
461
462
463
    }

    return false;
}

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
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

506
bool ResolveExpression::visit(SimpleNameAST *ast)
con's avatar
con committed
507
{
508
509
510
511
512
513
514
515
516
517
518
    QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
    QList<LookupItem> newCandidates;

    for (QList<LookupItem>::iterator it = candidates.begin(); it != candidates.end(); ++ it) {
        LookupItem& item = *it;
        if (!item.type()->isUndefinedType())
            continue;

        if (item.declaration() == 0)
            continue;

519
        if (item.type().isAuto()) {
520
521
522
523
524
525
526
527
            const Declaration *decl = item.declaration()->asDeclaration();
            if (!decl)
                continue;

            const StringLiteral *initializationString = decl->getInitializer();
            if (initializationString == 0)
                continue;

528
529
530
            const QByteArray &initializer =
                    QByteArray::fromRawData(initializationString->chars(),
                                            initializationString->size()).trimmed();
531
532
533
534
535
536

            // Skip lambda-function initializers
            if (initializer.length() > 0 && initializer[0] == '[')
                continue;

            TypeOfExpression exprTyper;
537
            Document::Ptr doc = _context.snapshot().document(decl->fileName());
538
539
            exprTyper.init(doc, _context.snapshot(), _context.bindings());

540
541
542
            Document::Ptr exprDoc =
                    documentForExpression(exprTyper.preprocessedExpression(initializer));
            exprDoc->check();
543
544
545

            DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit());
            if (deduceAuto._block)
546
547
                continue;

548
549
            const QList<LookupItem> &typeItems =
                    exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope());
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
            if (typeItems.empty())
                continue;

            CPlusPlus::Clone cloner(_context.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());
                }
                else {
                    LookupItem newItem(item);
                    newItem.setType(newType);
                    newItem.setScope(typeItems[n].scope());
                    newCandidates.push_back(newItem);
                }
            }
        }
        else {
            item.setType(item.declaration()->type());
            item.setScope(item.declaration()->enclosingScope());
        }
    }

575
    addResults(candidates);
576
    addResults(newCandidates);
con's avatar
con committed
577
578
579
    return false;
}

580
bool ResolveExpression::visit(TemplateIdAST *ast)
con's avatar
con committed
581
{
582
    const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
583
    addResults(candidates);
con's avatar
con committed
584
585
586
587
588
589
    return false;
}

bool ResolveExpression::visit(DestructorNameAST *)
{
    FullySpecifiedType ty(control()->voidType());
590
    addResult(ty, _scope);
con's avatar
con committed
591
592
593
    return false;
}

594
bool ResolveExpression::visit(OperatorFunctionIdAST *)
con's avatar
con committed
595
{
596
597
    return false;
}
con's avatar
con committed
598

599
600
bool ResolveExpression::visit(ConversionFunctionIdAST *)
{
con's avatar
con committed
601
602
603
    return false;
}

604
bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount)
605
{
606
607
    return funTy->maybeValidPrototype(actualArgumentCount);
}
608

609
610
611
612
613
614
615
bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
{
    if (sourceTy.isEqualTo(targetTy))
        return true;
    else if (sourceTy.simplified().isEqualTo(targetTy.simplified()))
        return true;
    return false;
616
617
}

con's avatar
con committed
618
619
bool ResolveExpression::visit(CallAST *ast)
{
620
    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
621

con's avatar
con committed
622
    // Compute the types of the actual arguments.
623
    unsigned actualArgumentCount = 0;
con's avatar
con committed
624

625
    QList< QList<LookupItem> > arguments;
626
    for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
627
628
629
        if (_reference)
            arguments.append(resolve(exprIt->value, _scope));

630
631
        ++actualArgumentCount;
    }
con's avatar
con committed
632

633
    if (_reference) {
634
635
        typedef std::multimap<int, LookupItem> LookupMap;
        LookupMap sortedResults;
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
        foreach (const LookupItem &base, baseResults) {
            if (Function *funTy = base.type()->asFunctionType()) {
                if (! maybeValidPrototype(funTy, actualArgumentCount))
                    continue;

                int score = 0;

                for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
                    const FullySpecifiedType formalTy = funTy->argumentAt(i)->type();

                    FullySpecifiedType actualTy;
                    if (i < unsigned(arguments.size())) {
                        const QList<LookupItem> actual = arguments.at(i);
                        if (actual.isEmpty())
                            continue;

                        actualTy = actual.first().type();
                    } else
                        actualTy = formalTy;

                    if (implicitConversion(actualTy, formalTy))
                        ++score;
                }

660
                sortedResults.insert(LookupMap::value_type(-score, base));
661
662
663
            }
        }

664
665
666
        _results.clear();
        for (LookupMap::const_iterator it = sortedResults.begin(); it != sortedResults.end(); ++it)
            _results.append(it->second);
667
668
669
670
671
672
        if (_results.isEmpty())
            _results = baseResults;

        return false;
    }

Roberto Raggi's avatar
Roberto Raggi committed
673
    const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
674

675
676
    foreach (const LookupItem &result, baseResults) {
        FullySpecifiedType ty = result.type().simplified();
677
        Scope *scope = result.scope();
678
679

        if (NamedType *namedTy = ty->asNamedType()) {
680
            if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
681
682
                foreach (const LookupItem &r, b->find(functionCallOp)) {
                    Symbol *overload = r.declaration();
683
684
                    if (Function *funTy = overload->type()->asFunctionType()) {
                        if (maybeValidPrototype(funTy, actualArgumentCount)) {
685
686
                            if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
                                addResult(proto->returnType().simplified(), scope);
687
                        }
688
689
                    }
                }
con's avatar
con committed
690
            }
691

692
        } else if (Function *funTy = ty->asFunctionType()) {
693
            if (maybeValidPrototype(funTy, actualArgumentCount))
694
                addResult(funTy->returnType().simplified(), scope);
695
696

        } else if (Class *classTy = ty->asClassType()) {
con's avatar
con committed
697
            // Constructor call
698
            FullySpecifiedType ctorTy = control()->namedType(classTy->name());
699
            addResult(ctorTy, scope);
con's avatar
con committed
700
701
702
703
704
705
706
707
        }
    }

    return false;
}

bool ResolveExpression::visit(ArrayAccessAST *ast)
{
708
    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
709
    const QList<LookupItem> indexResults = resolve(ast->expression, _scope);
con's avatar
con committed
710

Roberto Raggi's avatar
Roberto Raggi committed
711
    const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
con's avatar
con committed
712

713
714
    foreach (const LookupItem &result, baseResults) {
        FullySpecifiedType ty = result.type().simplified();
715
        Scope *scope = result.scope();
con's avatar
con committed
716
717

        if (PointerType *ptrTy = ty->asPointerType()) {
718
            addResult(ptrTy->elementType().simplified(), scope);
719

con's avatar
con committed
720
        } else if (ArrayType *arrTy = ty->asArrayType()) {
721
            addResult(arrTy->elementType().simplified(), scope);
722

con's avatar
con committed
723
        } else if (NamedType *namedTy = ty->asNamedType()) {
724
            if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
725
726
                foreach (const LookupItem &r, b->find(arrayAccessOp)) {
                    Symbol *overload = r.declaration();
727
                    if (Function *funTy = overload->type()->asFunctionType()) {
728
729
730
                        if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
                            // ### TODO: check the actual arguments
                            addResult(proto->returnType().simplified(), scope);
731
                    }
con's avatar
con committed
732
                }
733

con's avatar
con committed
734
735
736
737
738
739
            }
        }
    }
    return false;
}

740
741
QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
{
742
743
744
745
    Q_UNUSED(binding);
    Q_UNUSED(memberName);

    // ### port me
746
    QList<LookupItem> members;
Roberto Raggi's avatar
Roberto Raggi committed
747
#if 0
748
749
750
751
752
753
754
755
756
757
    const QList<LookupItem> originalMembers = binding->find(memberName);

    foreach (const LookupItem &m, originalMembers) {
        if (! m.binding() || ! m.binding()->templateId()) {
            members.append(m);
            continue;
        }

        Symbol *decl = m.declaration();

Roberto Raggi's avatar
Roberto Raggi committed
758
        if (Class *klass = decl->scope()->asClass()) {
759
760
761
762
763
764
765
766
767
768
769
            if (klass->templateParameters() != 0) {
                SubstitutionMap map;

                const TemplateNameId *templateId = m.binding()->templateId();
                unsigned count = qMin(klass->templateParameterCount(), templateId->templateArgumentCount());

                for (unsigned i = 0; i < count; ++i) {
                    map.bind(klass->templateParameterAt(i)->name(), templateId->templateArgumentAt(i));
                }

                SubstitutionEnvironment env;
770
771
772
                if (m.scope())
                    env.switchScope(m.scope());
                env.setContext(_context);
773
774

                env.enter(&map);
775
                FullySpecifiedType instantiatedTy = rewriteType(decl->type(), &env, _context.control().data());
776
777
778
779
780
781
782
783
784
785
786
787
788
789

                Overview oo;
                oo.setShowReturnTypes(true);
                oo.setShowFunctionSignatures(true);

                qDebug() << "original:" << oo(decl->type(), decl->name()) << "inst:" << oo(instantiatedTy, decl->name());

                LookupItem newItem;
                newItem = m;
                newItem.setType(instantiatedTy);
                members.append(newItem);
            }
        }
    }
Roberto Raggi's avatar
Roberto Raggi committed
790
#endif
791
792
793
794

    return members;
}

con's avatar
con committed
795
796
797
798
bool ResolveExpression::visit(MemberAccessAST *ast)
{
    // The candidate types for the base expression are stored in
    // _results.
799
    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
con's avatar
con committed
800
801

    // Evaluate the expression-id that follows the access operator.
Roberto Raggi's avatar
Roberto Raggi committed
802
    const Name *memberName = 0;
803
804
    if (ast->member_name)
        memberName = ast->member_name->name;
con's avatar
con committed
805
806

    // Remember the access operator.
807
    const int accessOp = tokenKind(ast->access_token);
con's avatar
con committed
808

809
810
    if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp))
        addResults(binding->lookup(memberName));
con's avatar
con committed
811
812
813
814

    return false;
}

815
816
817
ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope) const
{
    FullySpecifiedType ty = originalTy.simplified();
818
    ClassOrNamespace *binding = 0;
819
820

    if (Class *klass = ty->asClassType())
821
        binding = _context.lookupType(klass);
822
823

    else if (NamedType *namedTy = ty->asNamedType())
824
        binding = _context.lookupType(namedTy->name(), scope);
825

826
827
828
    else if (Function *funTy = ty->asFunctionType())
        return findClass(funTy->returnType(), scope);

829
830
831
    return binding;
}

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
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;
    }
}

864
865
866
867
868
869
ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
                                                    int accessOp,
                                                    bool *replacedDotOperator) const
{
    foreach (const LookupItem &r, baseResults) {
        FullySpecifiedType ty = r.type().simplified();
870
        Scope *scope = r.scope();
871

872
873
        resolveTypedefs(_context, &ty, &scope);

874
        if (accessOp == T_ARROW) {
875
            if (PointerType *ptrTy = ty->asPointerType()) {
876
877
878
                if (ClassOrNamespace *binding = findClass(ptrTy->elementType(), scope))
                    return binding;

879
            } else if (ClassOrNamespace *binding = findClass(ty, scope)) {
880
                // lookup for overloads of operator->
881

882
                const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
883
884
885
886
                foreach (const LookupItem &r, binding->find(arrowOp)) {
                    Symbol *overload = r.declaration();
                    if (! overload)
                        continue;
887
                    Scope *functionScope = overload->enclosingScope();
888

Roberto Raggi's avatar
Roberto Raggi committed
889
                    if (overload->type()->isFunctionType()) {
890
                        FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
891
892
893
894
895
                        Function *instantiatedFunction = overloadTy->asFunctionType();
                        Q_ASSERT(instantiatedFunction != 0);

                        FullySpecifiedType retTy = instantiatedFunction->returnType().simplified();

896
897
                        resolveTypedefs(_context, &retTy, &functionScope);

898
                        if (PointerType *ptrTy = retTy->asPointerType()) {
899
                            if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), functionScope))
900
                                return retBinding;
901

902
                            if (scope != functionScope) {
903
904
905
                                if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
                                    return retBinding;
                            }
906
907
908
909

                            if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
                                foreach (Symbol *originSymbol, origin->symbols()) {
                                    Scope *originScope = originSymbol->asScope();
910
                                    if (originScope && originScope != scope && originScope != functionScope) {
911
912
913
914
915
                                        if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), originScope))
                                            return retBinding;
                                    }
                                }
                            }
916
917
                        }
                    }
918
                }
919

920
            }
921
922
923
924
925
926
927
        } else if (accessOp == T_DOT) {
            if (replacedDotOperator) {
                if (PointerType *ptrTy = ty->asPointerType()) {
                    // replace . with ->
                    ty = ptrTy->elementType();
                    *replacedDotOperator = true;
                }
928
929
            }

930
931
932
            if (ClassOrNamespace *binding = findClass(ty, scope))
                return binding;
        }
933
934
935
936
937
    }

    return 0;
}

938
939
FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const
{
940
    return DeprecatedGenTemplateInstance::instantiate(className, candidate, _context.control());
941
942
}

943
bool ResolveExpression::visit(PostIncrDecrAST *ast)
con's avatar
con committed
944
{
945
946
    const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
    _results = baseResults;
con's avatar
con committed
947
948
    return false;
}
Roberto Raggi's avatar
Roberto Raggi committed
949

950
bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
951
{
952
    const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
953

954
    foreach (const LookupItem &result, receiverResults) {
955
        FullySpecifiedType ty = result.type().simplified();
956
        ClassOrNamespace *binding = 0;
957

958
        if (ObjCClass *clazz = ty->asObjCClassType()) {
959
            // static access, e.g.:
960
961
962
            //   [NSObject description];
            binding = _context.lookupType(clazz);
        } else if (PointerType *ptrTy = ty->asPointerType()) {
963
            if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
964
                // dynamic access, e.g.:
965
966
                //   NSObject *obj = ...; [obj release];
                binding = _context.lookupType(namedTy->name(), result.scope());
967
968
969
            }
        }

970
        if (binding) {
971
972
            foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
                Symbol *s = r.declaration();
973
974
                if (ObjCMethod *m = s->asObjCMethod())
                    addResult(m->returnType(), result.scope());
975
            }
976
        }
977
978
979
980
981
    }

    return false;
}

982
983
984
985
const LookupContext &ResolveExpression::context() const
{
    return _context;
}