tools/icheck/parser/src/libs/cplusplus/ResolveExpression.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "ResolveExpression.h"
       
    43 #include "LookupContext.h"
       
    44 #include "Overview.h"
       
    45 #include "GenTemplateInstance.h"
       
    46 
       
    47 #include <Control.h>
       
    48 #include <AST.h>
       
    49 #include <Scope.h>
       
    50 #include <Names.h>
       
    51 #include <Symbols.h>
       
    52 #include <Literals.h>
       
    53 #include <CoreTypes.h>
       
    54 #include <TypeVisitor.h>
       
    55 #include <NameVisitor.h>
       
    56 
       
    57 #include <QtCore/QList>
       
    58 #include <QtCore/QVarLengthArray>
       
    59 #include <QtCore/QtDebug>
       
    60 
       
    61 using namespace CPlusPlus;
       
    62 
       
    63 namespace {
       
    64 
       
    65 template <typename _Tp>
       
    66 static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
       
    67 {
       
    68     QList<_Tp> uniqueList;
       
    69     QSet<_Tp> processed;
       
    70     foreach (const _Tp &r, results) {
       
    71         if (processed.contains(r))
       
    72             continue;
       
    73 
       
    74         processed.insert(r);
       
    75         uniqueList.append(r);
       
    76     }
       
    77 
       
    78     return uniqueList;
       
    79 }
       
    80 
       
    81 } // end of anonymous namespace
       
    82 
       
    83 /////////////////////////////////////////////////////////////////////
       
    84 // ResolveExpression
       
    85 /////////////////////////////////////////////////////////////////////
       
    86 ResolveExpression::ResolveExpression(const LookupContext &context)
       
    87     : ASTVisitor(context.expressionDocument()->translationUnit()),
       
    88       _context(context),
       
    89       sem(context.expressionDocument()->translationUnit())
       
    90 { }
       
    91 
       
    92 ResolveExpression::~ResolveExpression()
       
    93 { }
       
    94 
       
    95 QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast)
       
    96 {
       
    97     const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
       
    98     accept(ast);
       
    99     return removeDuplicates(switchResults(previousResults));
       
   100 }
       
   101 
       
   102 QList<LookupItem>
       
   103 ResolveExpression::switchResults(const QList<LookupItem> &results)
       
   104 {
       
   105     const QList<LookupItem> previousResults = _results;
       
   106     _results = results;
       
   107     return previousResults;
       
   108 }
       
   109 
       
   110 void ResolveExpression::addResults(const QList<LookupItem> &results)
       
   111 {
       
   112     foreach (const LookupItem r, results)
       
   113         addResult(r);
       
   114 }
       
   115 
       
   116 void ResolveExpression::addResult(const FullySpecifiedType &ty, Symbol *symbol)
       
   117 { return addResult(LookupItem(ty, symbol)); }
       
   118 
       
   119 void ResolveExpression::addResult(const LookupItem &r)
       
   120 {
       
   121     LookupItem p = r;
       
   122 
       
   123     if (! p.lastVisibleSymbol())
       
   124         p.setLastVisibleSymbol(_context.symbol());
       
   125 
       
   126     if (! _results.contains(p))
       
   127         _results.append(p);
       
   128 }
       
   129 
       
   130 QList<Scope *> ResolveExpression::visibleScopes(const LookupItem &result) const
       
   131 { return _context.visibleScopes(result); }
       
   132 
       
   133 bool ResolveExpression::visit(BinaryExpressionAST *ast)
       
   134 {
       
   135     accept(ast->left_expression);
       
   136     return false;
       
   137 }
       
   138 
       
   139 bool ResolveExpression::visit(CastExpressionAST *ast)
       
   140 {
       
   141     addResult(sem.check(ast->type_id, _context.expressionDocument()->globalSymbols()));
       
   142     return false;
       
   143 }
       
   144 
       
   145 bool ResolveExpression::visit(ConditionAST *)
       
   146 {
       
   147     // nothing to do.
       
   148     return false;
       
   149 }
       
   150 
       
   151 bool ResolveExpression::visit(ConditionalExpressionAST *ast)
       
   152 {
       
   153     if (ast->left_expression)
       
   154         accept(ast->left_expression);
       
   155 
       
   156     else if (ast->right_expression)
       
   157         accept(ast->right_expression);
       
   158 
       
   159     return false;
       
   160 }
       
   161 
       
   162 bool ResolveExpression::visit(CppCastExpressionAST *ast)
       
   163 {
       
   164     addResult(sem.check(ast->type_id, _context.expressionDocument()->globalSymbols()));
       
   165     return false;
       
   166 }
       
   167 
       
   168 bool ResolveExpression::visit(DeleteExpressionAST *)
       
   169 {
       
   170     FullySpecifiedType ty(control()->voidType());
       
   171     addResult(ty);
       
   172     return false;
       
   173 }
       
   174 
       
   175 bool ResolveExpression::visit(ArrayInitializerAST *)
       
   176 {
       
   177     // nothing to do.
       
   178     return false;
       
   179 }
       
   180 
       
   181 bool ResolveExpression::visit(NewExpressionAST *ast)
       
   182 {
       
   183     if (ast->new_type_id) {
       
   184         Scope *scope = _context.expressionDocument()->globalSymbols();
       
   185         FullySpecifiedType ty = sem.check(ast->new_type_id->type_specifier_list, scope);
       
   186         ty = sem.check(ast->new_type_id->ptr_operator_list, ty, scope);
       
   187         FullySpecifiedType ptrTy(control()->pointerType(ty));
       
   188         addResult(ptrTy);
       
   189     }
       
   190     // nothing to do.
       
   191     return false;
       
   192 }
       
   193 
       
   194 bool ResolveExpression::visit(TypeidExpressionAST *)
       
   195 {
       
   196     const Name *std_type_info[2];
       
   197     std_type_info[0] = control()->nameId(control()->findOrInsertIdentifier("std"));
       
   198     std_type_info[1] = control()->nameId(control()->findOrInsertIdentifier("type_info"));
       
   199 
       
   200     const Name *q = control()->qualifiedNameId(std_type_info, 2, /*global=*/ true);
       
   201     FullySpecifiedType ty(control()->namedType(q));
       
   202     addResult(ty);
       
   203 
       
   204     return false;
       
   205 }
       
   206 
       
   207 bool ResolveExpression::visit(TypenameCallExpressionAST *)
       
   208 {
       
   209     // nothing to do
       
   210     return false;
       
   211 }
       
   212 
       
   213 bool ResolveExpression::visit(TypeConstructorCallAST *)
       
   214 {
       
   215     // nothing to do.
       
   216     return false;
       
   217 }
       
   218 
       
   219 bool ResolveExpression::visit(PostfixExpressionAST *ast)
       
   220 {
       
   221     accept(ast->base_expression);
       
   222 
       
   223     for (PostfixListAST *it = ast->postfix_expression_list; it; it = it->next) {
       
   224         accept(it->value);
       
   225     }
       
   226 
       
   227     return false;
       
   228 }
       
   229 
       
   230 bool ResolveExpression::visit(SizeofExpressionAST *)
       
   231 {
       
   232     FullySpecifiedType ty(control()->integerType(IntegerType::Int));
       
   233     ty.setUnsigned(true);
       
   234     addResult(ty);
       
   235     return false;
       
   236 }
       
   237 
       
   238 bool ResolveExpression::visit(NumericLiteralAST *ast)
       
   239 {
       
   240     Type *type = 0;
       
   241     const NumericLiteral *literal = numericLiteral(ast->literal_token);
       
   242 
       
   243     if (literal->isChar())
       
   244         type = control()->integerType(IntegerType::Char);
       
   245     else if (literal->isWideChar())
       
   246         type = control()->integerType(IntegerType::WideChar);
       
   247     else if (literal->isInt())
       
   248         type = control()->integerType(IntegerType::Int);
       
   249     else if (literal->isLong())
       
   250         type = control()->integerType(IntegerType::Long);
       
   251     else if (literal->isLongLong())
       
   252         type = control()->integerType(IntegerType::LongLong);
       
   253     else if (literal->isFloat())
       
   254         type = control()->floatType(FloatType::Float);
       
   255     else if (literal->isDouble())
       
   256         type = control()->floatType(FloatType::Double);
       
   257     else if (literal->isLongDouble())
       
   258         type = control()->floatType(FloatType::LongDouble);
       
   259     else
       
   260         type = control()->integerType(IntegerType::Int);
       
   261 
       
   262     FullySpecifiedType ty(type);
       
   263     if (literal->isUnsigned())
       
   264         ty.setUnsigned(true);
       
   265 
       
   266     addResult(ty);
       
   267     return false;
       
   268 }
       
   269 
       
   270 bool ResolveExpression::visit(BoolLiteralAST *)
       
   271 {
       
   272     FullySpecifiedType ty(control()->integerType(IntegerType::Bool));
       
   273     addResult(ty);
       
   274     return false;
       
   275 }
       
   276 
       
   277 bool ResolveExpression::visit(ThisExpressionAST *)
       
   278 {
       
   279     if (! _context.symbol())
       
   280         return false;
       
   281 
       
   282     Scope *scope = _context.symbol()->scope();
       
   283     for (; scope; scope = scope->enclosingScope()) {
       
   284         if (scope->isFunctionScope()) {
       
   285             Function *fun = scope->owner()->asFunction();
       
   286             if (Scope *cscope = scope->enclosingClassScope()) {
       
   287                 Class *klass = cscope->owner()->asClass();
       
   288                 FullySpecifiedType classTy(control()->namedType(klass->name()));
       
   289                 FullySpecifiedType ptrTy(control()->pointerType(classTy));
       
   290                 addResult(ptrTy, fun);
       
   291                 break;
       
   292             } else if (const QualifiedNameId *q = fun->name()->asQualifiedNameId()) {
       
   293                 const Name *nestedNameSpecifier = 0;
       
   294                 if (q->nameCount() == 1 && q->isGlobal())
       
   295                     nestedNameSpecifier = q->nameAt(0);
       
   296                 else
       
   297                     nestedNameSpecifier = control()->qualifiedNameId(q->names(), q->nameCount() - 1);
       
   298                 FullySpecifiedType classTy(control()->namedType(nestedNameSpecifier));
       
   299                 FullySpecifiedType ptrTy(control()->pointerType(classTy));
       
   300                 addResult(ptrTy, fun);
       
   301                 break;
       
   302             }
       
   303         }
       
   304     }
       
   305     return false;
       
   306 }
       
   307 
       
   308 bool ResolveExpression::visit(NestedExpressionAST *ast)
       
   309 {
       
   310     accept(ast->expression);
       
   311     return false;
       
   312 }
       
   313 
       
   314 bool ResolveExpression::visit(StringLiteralAST *)
       
   315 {
       
   316     FullySpecifiedType charTy = control()->integerType(IntegerType::Char);
       
   317     charTy.setConst(true);
       
   318     FullySpecifiedType ty(control()->pointerType(charTy));
       
   319     addResult(ty);
       
   320     return false;
       
   321 }
       
   322 
       
   323 bool ResolveExpression::visit(ThrowExpressionAST *)
       
   324 {
       
   325     return false;
       
   326 }
       
   327 
       
   328 bool ResolveExpression::visit(TypeIdAST *)
       
   329 {
       
   330     return false;
       
   331 }
       
   332 
       
   333 bool ResolveExpression::visit(UnaryExpressionAST *ast)
       
   334 {
       
   335     accept(ast->expression);
       
   336     unsigned unaryOp = tokenKind(ast->unary_op_token);
       
   337     if (unaryOp == T_AMPER) {
       
   338         QMutableListIterator<LookupItem > it(_results);
       
   339         while (it.hasNext()) {
       
   340             LookupItem p = it.next();
       
   341             FullySpecifiedType ty = p.type();
       
   342             ty.setType(control()->pointerType(ty));
       
   343             p.setType(ty);
       
   344             it.setValue(p);
       
   345         }
       
   346     } else if (unaryOp == T_STAR) {
       
   347         QMutableListIterator<LookupItem > it(_results);
       
   348         while (it.hasNext()) {
       
   349             LookupItem p = it.next();
       
   350             if (PointerType *ptrTy = p.type()->asPointerType()) {
       
   351                 p.setType(ptrTy->elementType());
       
   352                 it.setValue(p);
       
   353             } else {
       
   354                 it.remove();
       
   355             }
       
   356         }
       
   357     }
       
   358     return false;
       
   359 }
       
   360 
       
   361 bool ResolveExpression::visit(CompoundLiteralAST *ast)
       
   362 {
       
   363     accept(ast->type_id);
       
   364     return false;
       
   365 }
       
   366 
       
   367 bool ResolveExpression::visit(QualifiedNameAST *ast)
       
   368 {
       
   369     ResolveClass resolveClass;
       
   370     const Name *name = ast->name;
       
   371 
       
   372     QList<Symbol *> symbols = _context.resolve(name);
       
   373     foreach (Symbol *symbol, symbols) {
       
   374         if (symbol->isTypedef()) {
       
   375             if (NamedType *namedTy = symbol->type()->asNamedType()) {
       
   376                 const LookupItem r(namedTy, symbol);
       
   377                 const QList<Symbol *> resolvedClasses =
       
   378                         resolveClass(namedTy->name(), r, _context);
       
   379                 if (resolvedClasses.count()) {
       
   380                     foreach (Symbol *s, resolvedClasses) {
       
   381                         addResult(s->type(), s);
       
   382                     }
       
   383                     continue;
       
   384                 }
       
   385             }
       
   386         }
       
   387         addResult(symbol->type(), symbol);
       
   388     }
       
   389     return false;
       
   390 }
       
   391 
       
   392 bool ResolveExpression::visit(OperatorFunctionIdAST *)
       
   393 {
       
   394     return false;
       
   395 }
       
   396 
       
   397 bool ResolveExpression::visit(ConversionFunctionIdAST *)
       
   398 {
       
   399     return false;
       
   400 }
       
   401 
       
   402 bool ResolveExpression::visit(SimpleNameAST *ast)
       
   403 {
       
   404     QList<Symbol *> symbols = _context.resolve(ast->name);
       
   405     foreach (Symbol *symbol, symbols)
       
   406         addResult(symbol->type(), symbol);
       
   407 
       
   408     return false;
       
   409 }
       
   410 
       
   411 bool ResolveExpression::visit(DestructorNameAST *)
       
   412 {
       
   413     FullySpecifiedType ty(control()->voidType());
       
   414     addResult(ty);
       
   415     return false;
       
   416 }
       
   417 
       
   418 bool ResolveExpression::visit(TemplateIdAST *ast)
       
   419 {
       
   420     QList<Symbol *> symbols = _context.resolve(ast->name);
       
   421     foreach (Symbol *symbol, symbols)
       
   422         addResult(symbol->type(), symbol);
       
   423 
       
   424     return false;
       
   425 }
       
   426 
       
   427 bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const
       
   428 {
       
   429     unsigned minNumberArguments = 0;
       
   430 
       
   431     for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) {
       
   432         Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument();
       
   433 
       
   434         if (arg->hasInitializer())
       
   435             break;
       
   436     }
       
   437 
       
   438     if (actualArgumentCount < minNumberArguments) {
       
   439         // not enough arguments.
       
   440         return false;
       
   441 
       
   442     } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) {
       
   443         // too many arguments.
       
   444         return false;
       
   445     }
       
   446 
       
   447     return true;
       
   448 }
       
   449 
       
   450 bool ResolveExpression::visit(CallAST *ast)
       
   451 {
       
   452     ResolveClass resolveClass;
       
   453 
       
   454     const QList<LookupItem> baseResults = _results;
       
   455     _results.clear();
       
   456 
       
   457     // Compute the types of the actual arguments.
       
   458     int actualArgumentCount = 0;
       
   459 
       
   460     //QList< QList<Result> > arguments;
       
   461     for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
       
   462         //arguments.append(operator()(exprIt->expression));
       
   463         ++actualArgumentCount;
       
   464     }
       
   465 
       
   466     const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
       
   467 
       
   468     foreach (const LookupItem &result, baseResults) {
       
   469         FullySpecifiedType ty = result.type().simplified();
       
   470         Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
       
   471 
       
   472         if (NamedType *namedTy = ty->asNamedType()) {
       
   473             const QList<Symbol *> classObjectCandidates = resolveClass(namedTy->name(), result, _context);
       
   474 
       
   475             foreach (Symbol *classObject, classObjectCandidates) {
       
   476                 const QList<LookupItem> overloads = resolveMember(functionCallOp, classObject->asClass(), namedTy->name());
       
   477 
       
   478                 foreach (const LookupItem &o, overloads) {
       
   479                     FullySpecifiedType overloadTy = o.type().simplified();
       
   480 
       
   481                     if (Function *funTy = overloadTy->asFunctionType()) {
       
   482                         if (maybeValidPrototype(funTy, actualArgumentCount))
       
   483                             addResult(funTy->returnType().simplified(), lastVisibleSymbol);
       
   484                     }
       
   485                 }
       
   486             }
       
   487 
       
   488         } else if (Function *funTy = ty->asFunctionType()) {
       
   489             if (maybeValidPrototype(funTy, actualArgumentCount))
       
   490                 addResult(funTy->returnType().simplified(), lastVisibleSymbol);
       
   491 
       
   492         } else if (Class *classTy = ty->asClassType()) {
       
   493             // Constructor call
       
   494             FullySpecifiedType ctorTy = control()->namedType(classTy->name());
       
   495             addResult(ctorTy, lastVisibleSymbol);
       
   496         }
       
   497     }
       
   498 
       
   499     return false;
       
   500 }
       
   501 
       
   502 bool ResolveExpression::visit(ArrayAccessAST *ast)
       
   503 {
       
   504     const QList<LookupItem> baseResults = _results;
       
   505     _results.clear();
       
   506 
       
   507     const QList<LookupItem> indexResults = operator()(ast->expression);
       
   508     ResolveClass resolveClass;
       
   509 
       
   510     const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
       
   511 
       
   512     foreach (const LookupItem &result, baseResults) {
       
   513         FullySpecifiedType ty = result.type().simplified();
       
   514         Symbol *contextSymbol = result.lastVisibleSymbol();
       
   515 
       
   516         if (PointerType *ptrTy = ty->asPointerType()) {
       
   517             addResult(ptrTy->elementType().simplified(), contextSymbol);
       
   518 
       
   519         } else if (ArrayType *arrTy = ty->asArrayType()) {
       
   520             addResult(arrTy->elementType().simplified(), contextSymbol);
       
   521 
       
   522         } else if (NamedType *namedTy = ty->asNamedType()) {
       
   523             const QList<Symbol *> classObjectCandidates =
       
   524                     resolveClass(namedTy->name(), result, _context);
       
   525 
       
   526             foreach (Symbol *classObject, classObjectCandidates) {
       
   527                 Q_ASSERT(classObject->isClass());
       
   528 
       
   529                 const QList<LookupItem> overloads =
       
   530                         resolveMember(arrayAccessOp, classObject->asClass(), namedTy->name());
       
   531 
       
   532                 foreach (LookupItem r, overloads) {
       
   533                     FullySpecifiedType ty = r.type().simplified();
       
   534                     if (Function *funTy = ty->asFunctionType()) {
       
   535                         ty = funTy->returnType().simplified();
       
   536                         addResult(ty, funTy);
       
   537                     }
       
   538                 }
       
   539             }
       
   540         }
       
   541     }
       
   542     return false;
       
   543 }
       
   544 
       
   545 bool ResolveExpression::visit(MemberAccessAST *ast)
       
   546 {
       
   547     // The candidate types for the base expression are stored in
       
   548     // _results.
       
   549     QList<LookupItem> baseResults = _results;
       
   550 
       
   551     // Evaluate the expression-id that follows the access operator.
       
   552     const Name *memberName = 0;
       
   553     if (ast->member_name)
       
   554         memberName = ast->member_name->name;
       
   555 
       
   556     // Remember the access operator.
       
   557     const int accessOp = tokenKind(ast->access_token);
       
   558 
       
   559     _results = resolveMemberExpression(baseResults, accessOp, memberName);
       
   560 
       
   561     return false;
       
   562 }
       
   563 
       
   564 QList<LookupItem>
       
   565 ResolveExpression::resolveBaseExpression(const QList<LookupItem> &baseResults, int accessOp,
       
   566                                          bool *replacedDotOperator) const
       
   567 {
       
   568     QList<LookupItem> results;
       
   569 
       
   570     if (baseResults.isEmpty())
       
   571         return results;
       
   572 
       
   573     LookupItem result = baseResults.first();
       
   574     FullySpecifiedType ty = result.type().simplified();
       
   575     Symbol *lastVisibleSymbol = result.lastVisibleSymbol();
       
   576 
       
   577     if (Function *funTy = ty->asFunctionType()) {
       
   578         if (funTy->isAmbiguous())
       
   579             ty = funTy->returnType().simplified();
       
   580     }
       
   581 
       
   582     if (accessOp == T_ARROW)  {
       
   583         if (lastVisibleSymbol && ty->isClassType() && ! lastVisibleSymbol->isClass()) {
       
   584             // ### remove ! lastVisibleSymbol->isClass() from the condition.
       
   585             results.append(LookupItem(ty, lastVisibleSymbol));
       
   586 
       
   587         } else if (NamedType *namedTy = ty->asNamedType()) {
       
   588             // ### This code is pretty slow.
       
   589             const QList<Symbol *> candidates = _context.resolve(namedTy->name());
       
   590 
       
   591             foreach (Symbol *candidate, candidates) {
       
   592                 if (candidate->isTypedef()) {
       
   593                     FullySpecifiedType declTy = candidate->type().simplified();
       
   594                     const LookupItem r(declTy, candidate);
       
   595 
       
   596                     // update the result
       
   597                     result = r;
       
   598 
       
   599                     // refresh the cached ty and lastVisibileSymbol.
       
   600                     ty = result.type().simplified();
       
   601                     lastVisibleSymbol = result.lastVisibleSymbol();
       
   602                     break;
       
   603                 }
       
   604             }
       
   605         }
       
   606 
       
   607         if (NamedType *namedTy = ty->asNamedType()) {
       
   608             ResolveClass resolveClass;
       
   609             const Name *arrowAccessOp = control()->operatorNameId(OperatorNameId::ArrowOp);
       
   610             const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, _context);
       
   611 
       
   612             foreach (Symbol *classObject, candidates) {
       
   613                 const QList<LookupItem> overloads = resolveMember(arrowAccessOp, classObject->asClass(),
       
   614                                                               namedTy->name());
       
   615 
       
   616                 foreach (const LookupItem &r, overloads) {
       
   617                     FullySpecifiedType typeOfOverloadFunction = r.type().simplified();
       
   618                     Symbol *lastVisibleSymbol = r.lastVisibleSymbol();
       
   619                     Function *funTy = typeOfOverloadFunction->asFunctionType();
       
   620                     if (! funTy)
       
   621                         continue;
       
   622 
       
   623                     typeOfOverloadFunction = funTy->returnType().simplified();
       
   624 
       
   625                     if (PointerType *ptrTy = typeOfOverloadFunction->asPointerType()) {
       
   626                         FullySpecifiedType elementTy = ptrTy->elementType().simplified();
       
   627 
       
   628                         if (elementTy->isNamedType())
       
   629                             results.append(LookupItem(elementTy, lastVisibleSymbol));
       
   630                     }
       
   631                 }
       
   632             }
       
   633         } else if (PointerType *ptrTy = ty->asPointerType()) {
       
   634             FullySpecifiedType elementTy = ptrTy->elementType().simplified();
       
   635 
       
   636             if (elementTy->isNamedType() || elementTy->isClassType())
       
   637                 results.append(LookupItem(elementTy, lastVisibleSymbol));
       
   638         }
       
   639     } else if (accessOp == T_DOT) {
       
   640         if (replacedDotOperator) {
       
   641             if (PointerType *ptrTy = ty->asPointerType()) {
       
   642                 *replacedDotOperator = true;
       
   643                 ty = ptrTy->elementType().simplified();
       
   644             } else if (ArrayType *arrTy = ty->asArrayType()) {
       
   645                 *replacedDotOperator = true;
       
   646                 ty = arrTy->elementType().simplified();
       
   647             }
       
   648         }
       
   649 
       
   650         if (NamedType *namedTy = ty->asNamedType()) {
       
   651             const QList<Scope *> visibleScopes = _context.visibleScopes(result);
       
   652             const QList<Symbol *> candidates = _context.resolve(namedTy->name(), visibleScopes);
       
   653             foreach (Symbol *candidate, candidates) {
       
   654                 if (candidate->isTypedef() && candidate->type()->isNamedType()) {
       
   655                     ty = candidate->type();
       
   656                     lastVisibleSymbol = candidate;
       
   657                     break;
       
   658                 } else if (TypenameArgument *arg = candidate->asTypenameArgument()) {
       
   659                     ty = arg->type();
       
   660                     lastVisibleSymbol = candidate;
       
   661                     break;
       
   662                 }
       
   663             }
       
   664 
       
   665             results.append(LookupItem(ty, lastVisibleSymbol));
       
   666 
       
   667         } else if (Function *fun = ty->asFunctionType()) {
       
   668             Scope *funScope = fun->scope();
       
   669 
       
   670             if (funScope && (funScope->isBlockScope() || funScope->isNamespaceScope())) {
       
   671                 FullySpecifiedType retTy = fun->returnType().simplified();
       
   672                 results.append(LookupItem(retTy, lastVisibleSymbol));
       
   673             }
       
   674         }
       
   675     }
       
   676 
       
   677     return removeDuplicates(results);
       
   678 }
       
   679 
       
   680 QList<LookupItem>
       
   681 ResolveExpression::resolveMemberExpression(const QList<LookupItem> &baseResults,
       
   682                                            unsigned accessOp,
       
   683                                            const Name *memberName,
       
   684                                            bool *replacedDotOperator) const
       
   685 {
       
   686     ResolveClass resolveClass;
       
   687     QList<LookupItem> results;
       
   688 
       
   689     const QList<LookupItem> classObjectResults = resolveBaseExpression(baseResults, accessOp, replacedDotOperator);
       
   690     foreach (const LookupItem &r, classObjectResults) {
       
   691         FullySpecifiedType ty = r.type();
       
   692 
       
   693         if (Class *klass = ty->asClassType())
       
   694             results += resolveMember(memberName, klass);
       
   695 
       
   696         else if (NamedType *namedTy = ty->asNamedType()) {
       
   697             const Name *className = namedTy->name();
       
   698             const QList<Symbol *> classes = resolveClass(className, r, _context);
       
   699 
       
   700             foreach (Symbol *c, classes) {
       
   701                 if (Class *klass = c->asClass())
       
   702                     results += resolveMember(memberName, klass, className);
       
   703             }
       
   704         }
       
   705     }
       
   706 
       
   707     return removeDuplicates(results);
       
   708 }
       
   709 
       
   710 QList<LookupItem>
       
   711 ResolveExpression::resolveMember(const Name *memberName, Class *klass,
       
   712                                  const Name *className) const
       
   713 {
       
   714     QList<LookupItem> results;
       
   715 
       
   716     if (! className)
       
   717         className = klass->name();
       
   718 
       
   719     if (! className)
       
   720         return results;
       
   721 
       
   722     QList<Scope *> scopes;
       
   723     _context.expand(klass->members(), _context.visibleScopes(), &scopes);
       
   724 
       
   725     const QList<Symbol *> candidates = _context.resolve(memberName, scopes);
       
   726 
       
   727     foreach (Symbol *candidate, candidates) {
       
   728         FullySpecifiedType ty = candidate->type();
       
   729         const Name *unqualifiedNameId = className;
       
   730 
       
   731         if (const QualifiedNameId *q = className->asQualifiedNameId())
       
   732             unqualifiedNameId = q->unqualifiedNameId();
       
   733 
       
   734         if (const TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) {
       
   735             GenTemplateInstance::Substitution subst;
       
   736 
       
   737             for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
       
   738                 FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
       
   739 
       
   740                 if (i < klass->templateParameterCount()) {
       
   741                     const Name *templArgName = klass->templateParameterAt(i)->name();
       
   742                     if (templArgName && templArgName->identifier()) {
       
   743                         const Identifier *templArgId = templArgName->identifier();
       
   744                         subst.append(qMakePair(templArgId, templArgTy));
       
   745                     }
       
   746                 }
       
   747             }
       
   748 
       
   749             GenTemplateInstance inst(_context, subst);
       
   750             ty = inst(candidate);
       
   751         }
       
   752 
       
   753         results.append(LookupItem(ty, candidate));
       
   754     }
       
   755 
       
   756     return removeDuplicates(results);
       
   757 }
       
   758 
       
   759 
       
   760 QList<LookupItem>
       
   761 ResolveExpression::resolveMember(const Name *memberName, ObjCClass *klass) const
       
   762 {
       
   763     QList<LookupItem> results;
       
   764 
       
   765     if (!memberName || !klass)
       
   766         return results;
       
   767 
       
   768     QList<Scope *> scopes;
       
   769     _context.expand(klass->members(), _context.visibleScopes(), &scopes);
       
   770 
       
   771     QList<Symbol *> candidates = _context.resolve(memberName, scopes);
       
   772 
       
   773     foreach (Symbol *candidate, candidates) {
       
   774         FullySpecifiedType ty = candidate->type();
       
   775 
       
   776         results.append(LookupItem(ty, candidate));
       
   777     }
       
   778 
       
   779     return removeDuplicates(results);
       
   780 }
       
   781 
       
   782 bool ResolveExpression::visit(PostIncrDecrAST *)
       
   783 {
       
   784     return false;
       
   785 }
       
   786 
       
   787 bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
       
   788 {
       
   789     QList<LookupItem> receiverResults = operator()(ast->receiver_expression);
       
   790 
       
   791     if (!receiverResults.isEmpty()) {
       
   792         LookupItem result = receiverResults.first();
       
   793         FullySpecifiedType ty = result.type().simplified();
       
   794         const Name *klassName = 0;
       
   795 
       
   796         if (const ObjCClass *classTy = ty->asObjCClassType()) {
       
   797             // static access, e.g.:
       
   798             // [NSObject description];
       
   799             klassName = classTy->name();
       
   800         } else if (const PointerType *ptrTy = ty->asPointerType()) {
       
   801             const FullySpecifiedType pointeeTy = ptrTy->elementType();
       
   802             if (pointeeTy && pointeeTy->isNamedType()) {
       
   803                 // dynamic access, e.g.:
       
   804                 // NSObject *obj = ...; [obj release];
       
   805                 klassName = pointeeTy->asNamedType()->name();
       
   806             }
       
   807         }
       
   808 
       
   809         if (klassName&&ast->selector && ast->selector->selector_name) {
       
   810             ResolveObjCClass resolveObjCClass;
       
   811             QList<Symbol *> resolvedSymbols = resolveObjCClass(klassName, result, _context);
       
   812             foreach (Symbol *resolvedSymbol, resolvedSymbols)
       
   813                 if (ObjCClass *klass = resolvedSymbol->asObjCClass())
       
   814                     _results.append(resolveMember(ast->selector->selector_name, klass));
       
   815         }
       
   816     }
       
   817 
       
   818     return false;
       
   819 }
       
   820 
       
   821 ////////////////////////////////////////////////////////////////////////////////
       
   822 ResolveClass::ResolveClass()
       
   823 { }
       
   824 
       
   825 QList<Symbol *> ResolveClass::operator()(const Name *name,
       
   826                                          const LookupItem &p,
       
   827                                          const LookupContext &context)
       
   828 {
       
   829     const QList<LookupItem> previousBlackList = _blackList;
       
   830     const QList<Symbol *> symbols = resolveClass(name, p, context);
       
   831     _blackList = previousBlackList;
       
   832     return symbols;
       
   833 }
       
   834 
       
   835 QList<Symbol *> ResolveClass::resolveClass(const Name *name,
       
   836                                            const LookupItem &p,
       
   837                                            const LookupContext &context)
       
   838 {
       
   839     QList<Symbol *> resolvedSymbols;
       
   840 
       
   841     if (_blackList.contains(p))
       
   842         return resolvedSymbols;
       
   843 
       
   844     _blackList.append(p);
       
   845 
       
   846     const QList<Symbol *> candidates =
       
   847             context.resolve(name, context.visibleScopes(p));
       
   848 
       
   849     foreach (Symbol *candidate, candidates) {
       
   850         if (Class *klass = candidate->asClass()) {
       
   851             if (resolvedSymbols.contains(klass))
       
   852                 continue; // we already know about `klass'
       
   853             resolvedSymbols.append(klass);
       
   854         } else if (candidate->isTypedef()) {
       
   855             if (Declaration *decl = candidate->asDeclaration()) {
       
   856                 if (Class *asClass = decl->type()->asClassType()) {
       
   857                     // typedef struct { } Point;
       
   858                     // Point pt;
       
   859                     // pt.
       
   860                     resolvedSymbols.append(asClass);
       
   861                 } else {
       
   862                     // typedef Point Boh;
       
   863                     // Boh b;
       
   864                     // b.
       
   865                     FullySpecifiedType declType = decl->type().simplified();
       
   866                     if (NamedType *namedTy = declType->asNamedType()) {
       
   867                         const LookupItem r(declType, decl);
       
   868                         resolvedSymbols += resolveClass(namedTy->name(), r, context);
       
   869                     }
       
   870                 }
       
   871             }
       
   872         } else if (Declaration *decl = candidate->asDeclaration()) {
       
   873             if (Function *funTy = decl->type()->asFunctionType()) {
       
   874                 // QString foo("ciao");
       
   875                 // foo.
       
   876                 if (funTy->scope() && (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope())) {
       
   877                     FullySpecifiedType retTy = funTy->returnType().simplified();
       
   878                     if (NamedType *namedTy = retTy->asNamedType()) {
       
   879                         const LookupItem r(retTy, decl);
       
   880                         resolvedSymbols += resolveClass(namedTy->name(), r, context);
       
   881                     }
       
   882                 }
       
   883             }
       
   884         }
       
   885     }
       
   886 
       
   887     return resolvedSymbols;
       
   888 }
       
   889 
       
   890 ResolveObjCClass::ResolveObjCClass()
       
   891 {}
       
   892 
       
   893 QList<Symbol *> ResolveObjCClass::operator ()(const Name *name,
       
   894                                               const LookupItem &p,
       
   895                                               const LookupContext &context)
       
   896 {
       
   897     QList<Symbol *> resolvedSymbols;
       
   898 
       
   899     const QList<Symbol *> candidates =
       
   900             context.resolve(name, context.visibleScopes(p));
       
   901 
       
   902     foreach (Symbol *candidate, candidates) {
       
   903         if (ObjCClass *klass = candidate->asObjCClass()) {
       
   904             if (resolvedSymbols.contains(klass))
       
   905                 continue; // we already know about `klass'
       
   906             resolvedSymbols.append(klass);
       
   907         } else if (candidate->isTypedef()) {
       
   908             if (Declaration *decl = candidate->asDeclaration()) {
       
   909                 if (decl->type()->isObjCClassType()) {
       
   910                     ObjCClass *klass = decl->type()->asObjCClassType();
       
   911                     if (resolvedSymbols.contains(klass))
       
   912                         continue;
       
   913                     resolvedSymbols.append(klass);
       
   914                 }
       
   915             }
       
   916         }
       
   917     }
       
   918 
       
   919     return resolvedSymbols;
       
   920 }