1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "ResolveExpression.h"
35 #include "LookupContext.h"
37 #include "DeprecatedGenTemplateInstance.h"
38 #include "CppRewriter.h"
46 #include <CoreTypes.h>
47 #include <TypeVisitor.h>
48 #include <NameVisitor.h>
50 #include <QtCore/QList>
51 #include <QtCore/QtDebug>
53 using namespace CPlusPlus;
57 template <typename _Tp>
58 static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
60 QList<_Tp> uniqueList;
62 foreach (const _Tp &r, results) {
63 if (processed.contains(r))
73 } // end of anonymous namespace
75 /////////////////////////////////////////////////////////////////////
77 /////////////////////////////////////////////////////////////////////
78 ResolveExpression::ResolveExpression(const LookupContext &context)
79 : ASTVisitor(context.expressionDocument()->translationUnit()),
82 bind(context.expressionDocument()->translationUnit()),
86 ResolveExpression::~ResolveExpression()
89 QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope)
90 { return resolve(ast, scope); }
92 QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope)
93 { return resolve(ast, scope, true); }
95 QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref)
98 return QList<LookupItem>();
100 std::swap(_scope, scope);
101 std::swap(_reference, ref);
103 const QList<LookupItem> result = expression(ast);
105 std::swap(_reference, ref);
106 std::swap(_scope, scope);
111 QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast)
113 const QList<LookupItem> previousResults = switchResults(QList<LookupItem>());
115 return removeDuplicates(switchResults(previousResults));
118 QList<LookupItem> ResolveExpression::switchResults(const QList<LookupItem> &results)
120 const QList<LookupItem> previousResults = _results;
122 return previousResults;
125 void ResolveExpression::addResults(const QList<Symbol *> &symbols)
127 foreach (Symbol *symbol, symbols) {
129 item.setType(symbol->type());
130 item.setScope(symbol->enclosingScope());
131 item.setDeclaration(symbol);
132 _results.append(item);
136 void ResolveExpression::addResults(const QList<LookupItem> &items)
141 void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope)
145 item.setScope(scope);
147 _results.append(item);
150 bool ResolveExpression::visit(IdExpressionAST *ast)
156 bool ResolveExpression::visit(BinaryExpressionAST *ast)
158 if (tokenKind(ast->binary_op_token) == T_COMMA && ast->right_expression && ast->right_expression->asQtMethod() != 0) {
160 if (ast->left_expression && ast->left_expression->asQtMethod() != 0)
163 accept(ast->left_expression);
165 QtMethodAST *qtMethod = ast->right_expression->asQtMethod();
166 if (DeclaratorAST *d = qtMethod->declarator) {
167 if (d->core_declarator) {
168 if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) {
169 if (NameAST *nameAST = declaratorId->name) {
170 if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) {
172 addResults(binding->lookup(nameAST->name));
182 accept(ast->left_expression);
186 bool ResolveExpression::visit(CastExpressionAST *ast)
188 Scope *dummyScope = _context.expressionDocument()->globalNamespace();
189 FullySpecifiedType ty = bind(ast->type_id, dummyScope);
190 addResult(ty, _scope);
194 bool ResolveExpression::visit(ConditionAST *)
200 bool ResolveExpression::visit(ConditionalExpressionAST *ast)
202 if (ast->left_expression)
203 accept(ast->left_expression);
205 else if (ast->right_expression)
206 accept(ast->right_expression);
211 bool ResolveExpression::visit(CppCastExpressionAST *ast)
213 Scope *dummyScope = _context.expressionDocument()->globalNamespace();
214 FullySpecifiedType ty = bind(ast->type_id, dummyScope);
215 addResult(ty, _scope);
219 bool ResolveExpression::visit(DeleteExpressionAST *)
221 FullySpecifiedType ty(control()->voidType());
222 addResult(ty, _scope);
226 bool ResolveExpression::visit(ArrayInitializerAST *)
232 bool ResolveExpression::visit(NewExpressionAST *ast)
234 if (ast->new_type_id) {
235 Scope *dummyScope = _context.expressionDocument()->globalNamespace();
236 FullySpecifiedType ty = bind(ast->new_type_id, dummyScope);
237 FullySpecifiedType ptrTy(control()->pointerType(ty));
238 addResult(ptrTy, _scope);
244 bool ResolveExpression::visit(TypeidExpressionAST *)
246 const Name *stdName = control()->identifier("std");
247 const Name *tiName = control()->identifier("type_info");
248 const Name *q = control()->qualifiedNameId(control()->qualifiedNameId(/* :: */ 0, stdName), tiName);
250 FullySpecifiedType ty(control()->namedType(q));
251 addResult(ty, _scope);
256 bool ResolveExpression::visit(TypenameCallExpressionAST *)
262 bool ResolveExpression::visit(TypeConstructorCallAST *)
268 bool ResolveExpression::visit(SizeofExpressionAST *)
270 FullySpecifiedType ty(control()->integerType(IntegerType::Int));
271 ty.setUnsigned(true);
272 addResult(ty, _scope);
276 bool ResolveExpression::visit(NumericLiteralAST *ast)
278 const Token &tk = tokenAt(ast->literal_token);
281 bool isUnsigned = false;
283 if (tk.is(T_CHAR_LITERAL))
284 type = control()->integerType(IntegerType::Char);
285 else if (tk.is(T_WIDE_CHAR_LITERAL))
286 type = control()->integerType(IntegerType::WideChar);
287 else if (const NumericLiteral *literal = numericLiteral(ast->literal_token)) {
288 isUnsigned = literal->isUnsigned();
290 if (literal->isInt())
291 type = control()->integerType(IntegerType::Int);
292 else if (literal->isLong())
293 type = control()->integerType(IntegerType::Long);
294 else if (literal->isLongLong())
295 type = control()->integerType(IntegerType::LongLong);
296 else if (literal->isFloat())
297 type = control()->floatType(FloatType::Float);
298 else if (literal->isDouble())
299 type = control()->floatType(FloatType::Double);
300 else if (literal->isLongDouble())
301 type = control()->floatType(FloatType::LongDouble);
303 type = control()->integerType(IntegerType::Int);
306 FullySpecifiedType ty(type);
307 ty.setUnsigned(isUnsigned);
308 addResult(ty, _scope);
312 bool ResolveExpression::visit(BoolLiteralAST *)
314 FullySpecifiedType ty(control()->integerType(IntegerType::Bool));
315 addResult(ty, _scope);
319 bool ResolveExpression::visit(ThisExpressionAST *)
325 void ResolveExpression::thisObject()
327 Scope *scope = _scope;
328 for (; scope; scope = scope->enclosingScope()) {
329 if (Function *fun = scope->asFunction()) {
330 if (Class *klass = scope->enclosingClass()) {
331 FullySpecifiedType classTy(control()->namedType(klass->name()));
332 FullySpecifiedType ptrTy(control()->pointerType(classTy));
333 addResult(ptrTy, fun->enclosingScope());
335 } else if (const QualifiedNameId *q = fun->name()->asQualifiedNameId()) {
337 FullySpecifiedType classTy(control()->namedType(q->base()));
338 FullySpecifiedType ptrTy(control()->pointerType(classTy));
339 addResult(ptrTy, fun->enclosingScope());
347 bool ResolveExpression::visit(CompoundExpressionAST *ast)
349 CompoundStatementAST *cStmt = ast->statement;
350 if (cStmt && cStmt->statement_list) {
351 accept(cStmt->statement_list->lastValue());
356 bool ResolveExpression::visit(NestedExpressionAST *ast)
358 accept(ast->expression);
362 bool ResolveExpression::visit(StringLiteralAST *)
364 FullySpecifiedType charTy = control()->integerType(IntegerType::Char);
365 charTy.setConst(true);
366 FullySpecifiedType ty(control()->pointerType(charTy));
367 addResult(ty, _scope);
371 bool ResolveExpression::visit(ThrowExpressionAST *)
376 bool ResolveExpression::visit(TypeIdAST *)
381 bool ResolveExpression::visit(UnaryExpressionAST *ast)
383 accept(ast->expression);
384 unsigned unaryOp = tokenKind(ast->unary_op_token);
385 if (unaryOp == T_AMPER) {
386 QMutableListIterator<LookupItem > it(_results);
387 while (it.hasNext()) {
388 LookupItem p = it.next();
389 FullySpecifiedType ty = p.type();
390 ty.setType(control()->pointerType(ty));
394 } else if (unaryOp == T_STAR) {
395 QMutableListIterator<LookupItem > it(_results);
396 while (it.hasNext()) {
397 LookupItem p = it.next();
398 if (PointerType *ptrTy = p.type()->asPointerType()) {
399 p.setType(ptrTy->elementType());
409 bool ResolveExpression::visit(CompoundLiteralAST *ast)
411 accept(ast->type_id);
415 bool ResolveExpression::visit(QualifiedNameAST *ast)
417 if (const Name *name = ast->name) {
418 const QList<LookupItem> candidates = _context.lookup(name, _scope);
419 addResults(candidates);
425 bool ResolveExpression::visit(SimpleNameAST *ast)
427 const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
428 addResults(candidates);
432 bool ResolveExpression::visit(TemplateIdAST *ast)
434 const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
435 addResults(candidates);
439 bool ResolveExpression::visit(DestructorNameAST *)
441 FullySpecifiedType ty(control()->voidType());
442 addResult(ty, _scope);
446 bool ResolveExpression::visit(OperatorFunctionIdAST *)
451 bool ResolveExpression::visit(ConversionFunctionIdAST *)
456 bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount)
458 return funTy->maybeValidPrototype(actualArgumentCount);
461 bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const
463 if (sourceTy.isEqualTo(targetTy))
465 else if (sourceTy.simplified().isEqualTo(targetTy.simplified()))
470 bool ResolveExpression::visit(CallAST *ast)
472 const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
474 // Compute the types of the actual arguments.
475 unsigned actualArgumentCount = 0;
477 QList< QList<LookupItem> > arguments;
478 for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) {
480 arguments.append(resolve(exprIt->value, _scope));
482 ++actualArgumentCount;
487 foreach (const LookupItem &base, baseResults) {
488 if (Function *funTy = base.type()->asFunctionType()) {
489 if (! maybeValidPrototype(funTy, actualArgumentCount))
494 for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
495 const FullySpecifiedType formalTy = funTy->argumentAt(i)->type();
497 FullySpecifiedType actualTy;
498 if (i < unsigned(arguments.size())) {
499 const QList<LookupItem> actual = arguments.at(i);
500 if (actual.isEmpty())
503 actualTy = actual.first().type();
507 if (implicitConversion(actualTy, formalTy))
512 _results.prepend(base);
514 _results.append(base);
518 if (_results.isEmpty())
519 _results = baseResults;
524 const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp);
526 foreach (const LookupItem &result, baseResults) {
527 FullySpecifiedType ty = result.type().simplified();
528 Scope *scope = result.scope();
530 if (NamedType *namedTy = ty->asNamedType()) {
531 if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
532 foreach (const LookupItem &r, b->find(functionCallOp)) {
533 Symbol *overload = r.declaration();
534 if (Function *funTy = overload->type()->asFunctionType()) {
535 if (maybeValidPrototype(funTy, actualArgumentCount)) {
536 if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
537 addResult(proto->returnType().simplified(), scope);
543 } else if (Function *funTy = ty->asFunctionType()) {
544 if (maybeValidPrototype(funTy, actualArgumentCount))
545 addResult(funTy->returnType().simplified(), scope);
547 } else if (Class *classTy = ty->asClassType()) {
549 FullySpecifiedType ctorTy = control()->namedType(classTy->name());
550 addResult(ctorTy, scope);
557 bool ResolveExpression::visit(ArrayAccessAST *ast)
559 const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
560 const QList<LookupItem> indexResults = resolve(ast->expression, _scope);
562 const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp);
564 foreach (const LookupItem &result, baseResults) {
565 FullySpecifiedType ty = result.type().simplified();
566 Scope *scope = result.scope();
568 if (PointerType *ptrTy = ty->asPointerType()) {
569 addResult(ptrTy->elementType().simplified(), scope);
571 } else if (ArrayType *arrTy = ty->asArrayType()) {
572 addResult(arrTy->elementType().simplified(), scope);
574 } else if (NamedType *namedTy = ty->asNamedType()) {
575 if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
576 foreach (const LookupItem &r, b->find(arrayAccessOp)) {
577 Symbol *overload = r.declaration();
578 if (Function *funTy = overload->type()->asFunctionType()) {
579 if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
580 // ### TODO: check the actual arguments
581 addResult(proto->returnType().simplified(), scope);
591 QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
594 Q_UNUSED(memberName);
597 QList<LookupItem> members;
599 const QList<LookupItem> originalMembers = binding->find(memberName);
601 foreach (const LookupItem &m, originalMembers) {
602 if (! m.binding() || ! m.binding()->templateId()) {
607 Symbol *decl = m.declaration();
609 if (Class *klass = decl->scope()->asClass()) {
610 if (klass->templateParameters() != 0) {
613 const TemplateNameId *templateId = m.binding()->templateId();
614 unsigned count = qMin(klass->templateParameterCount(), templateId->templateArgumentCount());
616 for (unsigned i = 0; i < count; ++i) {
617 map.bind(klass->templateParameterAt(i)->name(), templateId->templateArgumentAt(i));
620 SubstitutionEnvironment env;
622 env.switchScope(m.scope());
623 env.setContext(_context);
626 FullySpecifiedType instantiatedTy = rewriteType(decl->type(), &env, _context.control().data());
629 oo.setShowReturnTypes(true);
630 oo.setShowFunctionSignatures(true);
632 qDebug() << "original:" << oo(decl->type(), decl->name()) << "inst:" << oo(instantiatedTy, decl->name());
636 newItem.setType(instantiatedTy);
637 members.append(newItem);
646 bool ResolveExpression::visit(MemberAccessAST *ast)
648 // The candidate types for the base expression are stored in
650 const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
652 // Evaluate the expression-id that follows the access operator.
653 const Name *memberName = 0;
654 if (ast->member_name)
655 memberName = ast->member_name->name;
657 // Remember the access operator.
658 const int accessOp = tokenKind(ast->access_token);
660 if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp))
661 addResults(binding->lookup(memberName));
666 ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope) const
668 FullySpecifiedType ty = originalTy.simplified();
669 ClassOrNamespace *binding = 0;
671 if (Class *klass = ty->asClassType())
672 binding = _context.lookupType(klass);
674 else if (NamedType *namedTy = ty->asNamedType())
675 binding = _context.lookupType(namedTy->name(), scope);
677 else if (Function *funTy = ty->asFunctionType())
678 return findClass(funTy->returnType(), scope);
683 ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
685 bool *replacedDotOperator) const
687 foreach (const LookupItem &r, baseResults) {
688 FullySpecifiedType ty = r.type().simplified();
689 Scope *scope = r.scope();
691 if (accessOp == T_ARROW) {
692 if (PointerType *ptrTy = ty->asPointerType()) {
693 if (ClassOrNamespace *binding = findClass(ptrTy->elementType(), scope))
696 } else if (ClassOrNamespace *binding = findClass(ty, scope)) {
697 // lookup for overloads of operator->
699 const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
700 foreach (const LookupItem &r, binding->find(arrowOp)) {
701 Symbol *overload = r.declaration();
705 if (overload->type()->isFunctionType()) {
706 FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
707 Function *instantiatedFunction = overloadTy->asFunctionType();
708 Q_ASSERT(instantiatedFunction != 0);
710 FullySpecifiedType retTy = instantiatedFunction->returnType().simplified();
712 if (PointerType *ptrTy = retTy->asPointerType()) {
713 if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), overload->enclosingScope()))
716 else if (scope != overload->enclosingScope()) {
717 if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
725 } else if (accessOp == T_DOT) {
726 if (replacedDotOperator) {
727 if (PointerType *ptrTy = ty->asPointerType()) {
729 ty = ptrTy->elementType();
730 *replacedDotOperator = true;
734 if (ClassOrNamespace *binding = findClass(ty, scope))
742 FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const
744 return DeprecatedGenTemplateInstance::instantiate(className, candidate, _context.control());
747 bool ResolveExpression::visit(PostIncrDecrAST *ast)
749 const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
750 _results = baseResults;
754 bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
756 const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope);
758 foreach (const LookupItem &result, receiverResults) {
759 FullySpecifiedType ty = result.type().simplified();
760 ClassOrNamespace *binding = 0;
762 if (ObjCClass *clazz = ty->asObjCClassType()) {
763 // static access, e.g.:
764 // [NSObject description];
765 binding = _context.lookupType(clazz);
766 } else if (PointerType *ptrTy = ty->asPointerType()) {
767 if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) {
768 // dynamic access, e.g.:
769 // NSObject *obj = ...; [obj release];
770 binding = _context.lookupType(namedTy->name(), result.scope());
775 foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
776 Symbol *s = r.declaration();
777 if (ObjCMethod *m = s->asObjCMethod())
778 addResult(m->returnType(), result.scope());
786 const LookupContext &ResolveExpression::context() const