| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | /***************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Contact:  Qt Software Information (qt-info@nokia.com) | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** Non-Open Source Usage | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** Licensees may use this file in accordance with the Qt Beta Version | 
					
						
							|  |  |  | ** License Agreement, Agreement version 2.2 provided with the Software or, | 
					
						
							|  |  |  | ** alternatively, in accordance with the terms contained in a written | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** GNU General Public License Usage | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** Alternatively, this file may be used under the terms of the GNU General | 
					
						
							|  |  |  | ** Public License versions 2.0 or 3.0 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation and appearing in the file LICENSE.GPL included in the packaging | 
					
						
							|  |  |  | ** of this file.  Please review the following information to ensure GNU | 
					
						
							|  |  |  | ** General Public Licensing requirements will be met: | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
 | 
					
						
							|  |  |  | ** http://www.gnu.org/copyleft/gpl.html.
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** rights. These rights are described in the Nokia Qt GPL Exception | 
					
						
							| 
									
										
										
										
											2008-12-16 17:20:00 +01:00
										 |  |  | ** version 1.3, included in the file GPL_EXCEPTION.txt in this package. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ***************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ResolveExpression.h"
 | 
					
						
							|  |  |  | #include "LookupContext.h"
 | 
					
						
							|  |  |  | #include "Overview.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:09:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | #include <QtCore/QList>
 | 
					
						
							|  |  |  | #include <QtCore/QtDebug>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | namespace { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef QList< QPair<Name *, FullySpecifiedType> > Substitution; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Instantiation: protected TypeVisitor, protected NameVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Control *_control; | 
					
						
							|  |  |  |     FullySpecifiedType _type; | 
					
						
							|  |  |  |     const Substitution _substitution; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Instantiation(Control *control, const Substitution &substitution) | 
					
						
							|  |  |  |         : _control(control), | 
					
						
							|  |  |  |           _substitution(substitution) | 
					
						
							|  |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FullySpecifiedType operator()(const FullySpecifiedType &ty) | 
					
						
							|  |  |  |     { return subst(ty); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     FullySpecifiedType subst(Name *name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         for (int i = 0; i < _substitution.size(); ++i) { | 
					
						
							|  |  |  |             const QPair<Name *, FullySpecifiedType> s = _substitution.at(i); | 
					
						
							|  |  |  |             if (name->isEqualTo(s.first)) | 
					
						
							|  |  |  |                 return s.second; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return _control->namedType(name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FullySpecifiedType subst(const FullySpecifiedType &ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FullySpecifiedType previousType = switchType(ty); | 
					
						
							|  |  |  |         TypeVisitor::accept(ty.type()); | 
					
						
							|  |  |  |         return switchType(previousType); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FullySpecifiedType switchType(const FullySpecifiedType &type) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FullySpecifiedType previousType = _type; | 
					
						
							|  |  |  |         _type = type; | 
					
						
							|  |  |  |         return previousType; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // types
 | 
					
						
							|  |  |  |     virtual void visit(PointerToMemberType * /*ty*/) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |         Q_ASSERT(false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(PointerType *ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FullySpecifiedType elementType = subst(ty->elementType()); | 
					
						
							|  |  |  |         _type.setType(_control->pointerType(elementType)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(ReferenceType *ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FullySpecifiedType elementType = subst(ty->elementType()); | 
					
						
							|  |  |  |         _type.setType(_control->referenceType(elementType)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(ArrayType *ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         FullySpecifiedType elementType = subst(ty->elementType()); | 
					
						
							|  |  |  |         _type.setType(_control->arrayType(elementType, ty->size())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(NamedType *ty) | 
					
						
							|  |  |  |     { _type.setType(subst(ty->name()).type()); } // ### merge the specifiers
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(Function *ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Name *name = ty->name(); | 
					
						
							|  |  |  |         FullySpecifiedType returnType = subst(ty->returnType()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Function *fun = _control->newFunction(0, name); | 
					
						
							|  |  |  |         fun->setScope(ty->scope()); | 
					
						
							|  |  |  |         fun->setReturnType(returnType); | 
					
						
							|  |  |  |         for (unsigned i = 0; i < ty->argumentCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *arg = ty->argumentAt(i); | 
					
						
							|  |  |  |             FullySpecifiedType argTy = subst(arg->type()); | 
					
						
							|  |  |  |             Argument *newArg = _control->newArgument(0, arg->name()); | 
					
						
							|  |  |  |             newArg->setType(argTy); | 
					
						
							|  |  |  |             fun->arguments()->enterSymbol(newArg); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         _type.setType(fun); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(VoidType *) | 
					
						
							|  |  |  |     { /* nothing to do*/ } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(IntegerType *) | 
					
						
							|  |  |  |     { /* nothing to do*/ } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(FloatType *) | 
					
						
							|  |  |  |     { /* nothing to do*/ } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(Namespace *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(Class *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(Enum *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // names
 | 
					
						
							|  |  |  |     virtual void visit(NameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(TemplateNameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(DestructorNameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(OperatorNameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(ConversionNameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(QualifiedNameId *) | 
					
						
							| 
									
										
										
										
											2008-12-10 15:43:17 +01:00
										 |  |  |     { Q_ASSERT(false); } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // ResolveExpression
 | 
					
						
							|  |  |  | /////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | ResolveExpression::ResolveExpression(const LookupContext &context) | 
					
						
							|  |  |  |     : ASTVisitor(context.expressionDocument()->control()), | 
					
						
							|  |  |  |       _context(context), | 
					
						
							|  |  |  |       sem(_context.control()) | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ResolveExpression::~ResolveExpression() | 
					
						
							|  |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> ResolveExpression::operator()(ExpressionAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QList<Result> previousResults = switchResults(QList<Result>()); | 
					
						
							|  |  |  |     accept(ast); | 
					
						
							|  |  |  |     return switchResults(previousResults); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::switchResults(const QList<ResolveExpression::Result> &results) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QList<Result> previousResults = _results; | 
					
						
							|  |  |  |     _results = results; | 
					
						
							|  |  |  |     return previousResults; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResolveExpression::addResults(const QList<Result> &results) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const Result r, results) | 
					
						
							|  |  |  |         addResult(r); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResolveExpression::addResult(const FullySpecifiedType &ty, Symbol *symbol) | 
					
						
							|  |  |  | { return addResult(Result(ty, symbol)); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResolveExpression::addResult(const Result &r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Result p = r; | 
					
						
							|  |  |  |     if (! p.second) | 
					
						
							|  |  |  |         p.second = _context.symbol(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (! _results.contains(p)) | 
					
						
							|  |  |  |         _results.append(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<Scope *> ResolveExpression::visibleScopes(const Result &result) const | 
					
						
							|  |  |  | { return _context.visibleScopes(result); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ExpressionListAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 15:52:17 +01:00
										 |  |  | bool ResolveExpression::visit(BinaryExpressionAST *ast) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-04 15:52:17 +01:00
										 |  |  |     accept(ast->left_expression); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(CastExpressionAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Scope dummy; | 
					
						
							|  |  |  |     addResult(sem.check(ast->type_id, &dummy)); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ConditionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ConditionalExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(CppCastExpressionAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Scope dummy; | 
					
						
							|  |  |  |     addResult(sem.check(ast->type_id, &dummy)); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(DeleteExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ArrayInitializerAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(NewExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(TypeidExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Name *std_type_info[2]; | 
					
						
							|  |  |  |     std_type_info[0] = control()->nameId(control()->findOrInsertIdentifier("std")); | 
					
						
							|  |  |  |     std_type_info[1] = control()->nameId(control()->findOrInsertIdentifier("type_info")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Name *q = control()->qualifiedNameId(std_type_info, 2, /*global=*/ true); | 
					
						
							|  |  |  |     FullySpecifiedType ty(control()->namedType(q)); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(TypenameCallExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(TypeConstructorCallAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(PostfixExpressionAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     accept(ast->base_expression); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (PostfixAST *fx = ast->postfix_expressions; fx; fx = fx->next) { | 
					
						
							|  |  |  |         accept(fx); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(SizeofExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FullySpecifiedType ty(control()->integerType(IntegerType::Int)); | 
					
						
							|  |  |  |     ty.setUnsigned(true); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(NumericLiteralAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FullySpecifiedType ty(control()->integerType(IntegerType::Int)); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(BoolLiteralAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FullySpecifiedType ty(control()->integerType(IntegerType::Bool)); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ThisExpressionAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (! _context.symbol()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Scope *scope = _context.symbol()->scope(); | 
					
						
							|  |  |  |     for (; scope; scope = scope->enclosingScope()) { | 
					
						
							|  |  |  |         if (scope->isFunctionScope()) { | 
					
						
							|  |  |  |             Function *fun = scope->owner()->asFunction(); | 
					
						
							|  |  |  |             if (Scope *cscope = scope->enclosingClassScope()) { | 
					
						
							|  |  |  |                 Class *klass = cscope->owner()->asClass(); | 
					
						
							|  |  |  |                 FullySpecifiedType classTy(control()->namedType(klass->name())); | 
					
						
							|  |  |  |                 FullySpecifiedType ptrTy(control()->pointerType(classTy)); | 
					
						
							|  |  |  |                 addResult(ptrTy, fun); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } else if (QualifiedNameId *q = fun->name()->asQualifiedNameId()) { | 
					
						
							|  |  |  |                 Name *nestedNameSpecifier = 0; | 
					
						
							|  |  |  |                 if (q->nameCount() == 1 && q->isGlobal()) | 
					
						
							|  |  |  |                     nestedNameSpecifier = q->nameAt(0); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     nestedNameSpecifier = control()->qualifiedNameId(q->names(), q->nameCount() - 1); | 
					
						
							|  |  |  |                 FullySpecifiedType classTy(control()->namedType(nestedNameSpecifier)); | 
					
						
							|  |  |  |                 FullySpecifiedType ptrTy(control()->pointerType(classTy)); | 
					
						
							|  |  |  |                 addResult(ptrTy, fun); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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)); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  |     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) { | 
					
						
							|  |  |  |         QMutableListIterator<Result > it(_results); | 
					
						
							|  |  |  |         while (it.hasNext()) { | 
					
						
							|  |  |  |             Result p = it.next(); | 
					
						
							|  |  |  |             p.first.setType(control()->pointerType(p.first)); | 
					
						
							|  |  |  |             it.setValue(p); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (unaryOp == T_STAR) { | 
					
						
							|  |  |  |         QMutableListIterator<Result > it(_results); | 
					
						
							|  |  |  |         while (it.hasNext()) { | 
					
						
							|  |  |  |             Result p = it.next(); | 
					
						
							|  |  |  |             if (PointerType *ptrTy = p.first->asPointerType()) { | 
					
						
							|  |  |  |                 p.first = ptrTy->elementType(); | 
					
						
							|  |  |  |                 it.setValue(p); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 it.remove(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(QualifiedNameAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     ResolveClass symbolsForDotAcces; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Scope dummy; | 
					
						
							|  |  |  |     Name *name = sem.check(ast, &dummy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Symbol *> symbols = _context.resolve(name); | 
					
						
							|  |  |  |     foreach (Symbol *symbol, symbols) { | 
					
						
							|  |  |  |         if (symbol->isTypedef()) { | 
					
						
							|  |  |  |             if (NamedType *namedTy = symbol->type()->asNamedType()) { | 
					
						
							|  |  |  |                 LookupContext symbolContext(symbol, _context); | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  |                 const Result r(namedTy, symbol); | 
					
						
							|  |  |  |                 const QList<Symbol *> resolvedClasses = symbolsForDotAcces(r, _context); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 if (resolvedClasses.count()) { | 
					
						
							|  |  |  |                     foreach (Symbol *s, resolvedClasses) { | 
					
						
							|  |  |  |                         addResult(s->type(), s); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         addResult(symbol->type(), symbol); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(OperatorFunctionIdAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ConversionFunctionIdAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(SimpleNameAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Scope dummy; | 
					
						
							|  |  |  |     Name *name = sem.check(ast, &dummy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Symbol *> symbols = _context.resolve(name); | 
					
						
							|  |  |  |     foreach (Symbol *symbol, symbols) | 
					
						
							|  |  |  |         addResult(symbol->type(), symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(DestructorNameAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FullySpecifiedType ty(control()->voidType()); | 
					
						
							|  |  |  |     addResult(ty); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(TemplateIdAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Scope dummy; | 
					
						
							|  |  |  |     Name *name = sem.check(ast, &dummy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Symbol *> symbols = _context.resolve(name); | 
					
						
							|  |  |  |     foreach (Symbol *symbol, symbols) | 
					
						
							|  |  |  |         addResult(symbol->type(), symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(CallAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Compute the types of the actual arguments.
 | 
					
						
							|  |  |  |     QList< QList<Result> > arguments; | 
					
						
							|  |  |  |     for (ExpressionListAST *exprIt = ast->expression_list; exprIt; | 
					
						
							|  |  |  |             exprIt = exprIt->next) { | 
					
						
							|  |  |  |         arguments.append(operator()(exprIt->expression)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Result> baseResults = _results; | 
					
						
							|  |  |  |     _results.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Result p, baseResults) { | 
					
						
							|  |  |  |         if (Function *funTy = p.first->asFunction()) { | 
					
						
							|  |  |  |             unsigned minNumberArguments = 0; | 
					
						
							|  |  |  |             for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) { | 
					
						
							|  |  |  |                 Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument(); | 
					
						
							|  |  |  |                 if (arg->hasInitializer()) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const unsigned actualArgumentCount = arguments.count(); | 
					
						
							|  |  |  |             if (actualArgumentCount < minNumberArguments) { | 
					
						
							|  |  |  |                 // not enough arguments.
 | 
					
						
							|  |  |  |             } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) { | 
					
						
							|  |  |  |                 // too many arguments.
 | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 p.first = funTy->returnType(); | 
					
						
							|  |  |  |                 addResult(p); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (Class *classTy = p.first->asClass()) { | 
					
						
							|  |  |  |             // Constructor call
 | 
					
						
							|  |  |  |             p.first = control()->namedType(classTy->name()); | 
					
						
							|  |  |  |             addResult(p); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(ArrayAccessAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QList<Result> baseResults = _results; | 
					
						
							|  |  |  |     _results.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QList<Result> indexResults = operator()(ast->expression); | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     ResolveClass symbolsForDotAcccess; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     foreach (Result p, baseResults) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = p.first; | 
					
						
							|  |  |  |         Symbol *contextSymbol = p.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ReferenceType *refTy = ty->asReferenceType()) | 
					
						
							|  |  |  |             ty = refTy->elementType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (PointerType *ptrTy = ty->asPointerType()) { | 
					
						
							|  |  |  |             addResult(ptrTy->elementType(), contextSymbol); | 
					
						
							|  |  |  |         } else if (ArrayType *arrTy = ty->asArrayType()) { | 
					
						
							|  |  |  |             addResult(arrTy->elementType(), contextSymbol); | 
					
						
							|  |  |  |         } else if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  |             const QList<Symbol *> classObjectCandidates = | 
					
						
							|  |  |  |                     symbolsForDotAcccess(p, _context); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             foreach (Symbol *classObject, classObjectCandidates) { | 
					
						
							|  |  |  |                 const QList<Result> overloads = resolveArrayOperator(p, namedTy, | 
					
						
							|  |  |  |                                                                      classObject->asClass()); | 
					
						
							|  |  |  |                 foreach (Result r, overloads) { | 
					
						
							|  |  |  |                     FullySpecifiedType ty = r.first; | 
					
						
							|  |  |  |                     Function *funTy = ty->asFunction(); | 
					
						
							|  |  |  |                     if (! funTy) | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     ty = funTy->returnType(); | 
					
						
							|  |  |  |                     addResult(ty, funTy); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(MemberAccessAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // The candidate types for the base expression are stored in
 | 
					
						
							|  |  |  |     // _results.
 | 
					
						
							|  |  |  |     QList<Result> baseResults = _results; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Evaluate the expression-id that follows the access operator.
 | 
					
						
							|  |  |  |     Scope dummy; | 
					
						
							|  |  |  |     Name *memberName = sem.check(ast->member_name, &dummy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remember the access operator.
 | 
					
						
							|  |  |  |     const unsigned accessOp = tokenKind(ast->access_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _results = resolveMemberExpression(baseResults, accessOp, memberName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults, | 
					
						
							|  |  |  |                                            unsigned accessOp, | 
					
						
							|  |  |  |                                            Name *memberName) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     ResolveClass resolveClass; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QList<Result> results; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (accessOp == T_ARROW) { | 
					
						
							|  |  |  |         foreach (Result p, baseResults) { | 
					
						
							|  |  |  |             FullySpecifiedType ty = p.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ReferenceType *refTy = ty->asReferenceType()) | 
					
						
							|  |  |  |                 ty = refTy->elementType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  |                 const QList<Symbol *> classObjectCandidates = | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |                         resolveClass(namedTy, p, _context); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 foreach (Symbol *classObject, classObjectCandidates) { | 
					
						
							|  |  |  |                     const QList<Result> overloads = resolveArrowOperator(p, namedTy, | 
					
						
							|  |  |  |                                                                          classObject->asClass()); | 
					
						
							|  |  |  |                     foreach (Result r, overloads) { | 
					
						
							|  |  |  |                         FullySpecifiedType ty = r.first; | 
					
						
							|  |  |  |                         Function *funTy = ty->asFunction(); | 
					
						
							|  |  |  |                         if (! funTy) | 
					
						
							|  |  |  |                             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         ty = funTy->returnType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (ReferenceType *refTy = ty->asReferenceType()) | 
					
						
							|  |  |  |                             ty = refTy->elementType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (PointerType *ptrTy = ty->asPointerType()) { | 
					
						
							|  |  |  |                             if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) | 
					
						
							|  |  |  |                                 results += resolveMember(r, memberName, namedTy); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else if (PointerType *ptrTy = ty->asPointerType()) { | 
					
						
							|  |  |  |                 if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) | 
					
						
							|  |  |  |                     results += resolveMember(p, memberName, namedTy); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (accessOp == T_DOT) { | 
					
						
							|  |  |  |         // The base expression shall be a "class object" of a complete type.
 | 
					
						
							|  |  |  |         foreach (Result p, baseResults) { | 
					
						
							|  |  |  |             FullySpecifiedType ty = p.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ReferenceType *refTy = ty->asReferenceType()) | 
					
						
							|  |  |  |                 ty = refTy->elementType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (NamedType *namedTy = ty->asNamedType()) | 
					
						
							|  |  |  |                 results += resolveMember(p, memberName, namedTy); | 
					
						
							|  |  |  |             else if (Function *fun = ty->asFunction()) { | 
					
						
							|  |  |  |                 if (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()) { | 
					
						
							|  |  |  |                     ty = fun->returnType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (ReferenceType *refTy = ty->asReferenceType()) | 
					
						
							|  |  |  |                         ty = refTy->elementType(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (NamedType *namedTy = ty->asNamedType()) | 
					
						
							|  |  |  |                         results += resolveMember(p, memberName, namedTy); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::resolveMember(const Result &p, | 
					
						
							|  |  |  |                                  Name *memberName, | 
					
						
							|  |  |  |                                  NamedType *namedTy) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     ResolveClass resolveClass; | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const QList<Symbol *> classObjectCandidates = | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |             resolveClass(namedTy, p, _context); | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QList<Result> results; | 
					
						
							|  |  |  |     foreach (Symbol *classObject, classObjectCandidates) { | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  |         results += resolveMember(p, memberName, namedTy, | 
					
						
							|  |  |  |                                  classObject->asClass()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::resolveMember(const Result &, | 
					
						
							|  |  |  |                                  Name *memberName, | 
					
						
							|  |  |  |                                  NamedType *namedTy, | 
					
						
							|  |  |  |                                  Class *klass) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  |     _context.expand(klass->members(), _context.visibleScopes(), &scopes); | 
					
						
							|  |  |  |     QList<Result> results; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Symbol *> candidates = _context.resolve(memberName, scopes); | 
					
						
							|  |  |  |     foreach (Symbol *candidate, candidates) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = candidate->type(); | 
					
						
							|  |  |  |         Name *unqualifiedNameId = namedTy->name(); | 
					
						
							|  |  |  |         if (QualifiedNameId *q = namedTy->name()->asQualifiedNameId()) | 
					
						
							|  |  |  |             unqualifiedNameId = q->unqualifiedNameId(); | 
					
						
							|  |  |  |         if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { | 
					
						
							|  |  |  |             Substitution subst; | 
					
						
							|  |  |  |             for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { | 
					
						
							|  |  |  |                 FullySpecifiedType templArgTy = templId->templateArgumentAt(i); | 
					
						
							|  |  |  |                 if (i < klass->templateParameterCount()) { | 
					
						
							|  |  |  |                     subst.append(qMakePair(klass->templateParameterAt(i)->name(), | 
					
						
							|  |  |  |                                            templArgTy)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Instantiation inst(control(), subst); | 
					
						
							|  |  |  |             ty = inst(ty); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Result result(ty, candidate); | 
					
						
							|  |  |  |         if (! results.contains(result)) | 
					
						
							|  |  |  |             results.append(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::resolveArrowOperator(const Result &, | 
					
						
							|  |  |  |                                         NamedType *namedTy, | 
					
						
							|  |  |  |                                         Class *klass) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  |     _context.expand(klass->members(), _context.visibleScopes(), &scopes); | 
					
						
							|  |  |  |     QList<Result> results; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Name *memberName = control()->operatorNameId(OperatorNameId::ArrowOp); | 
					
						
							|  |  |  |     QList<Symbol *> candidates = _context.resolve(memberName, scopes); | 
					
						
							|  |  |  |     foreach (Symbol *candidate, candidates) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = candidate->type(); | 
					
						
							|  |  |  |         Name *unqualifiedNameId = namedTy->name(); | 
					
						
							|  |  |  |         if (QualifiedNameId *q = namedTy->name()->asQualifiedNameId()) | 
					
						
							|  |  |  |             unqualifiedNameId = q->unqualifiedNameId(); | 
					
						
							|  |  |  |         if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { | 
					
						
							|  |  |  |             Substitution subst; | 
					
						
							|  |  |  |             for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { | 
					
						
							|  |  |  |                 FullySpecifiedType templArgTy = templId->templateArgumentAt(i); | 
					
						
							|  |  |  |                 if (i < klass->templateParameterCount()) { | 
					
						
							|  |  |  |                     subst.append(qMakePair(klass->templateParameterAt(i)->name(), | 
					
						
							|  |  |  |                                            templArgTy)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Instantiation inst(control(), subst); | 
					
						
							|  |  |  |             ty = inst(ty); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Result result(ty, candidate); | 
					
						
							|  |  |  |         if (! results.contains(result)) | 
					
						
							|  |  |  |             results.append(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<ResolveExpression::Result> | 
					
						
							|  |  |  | ResolveExpression::resolveArrayOperator(const Result &, | 
					
						
							|  |  |  |                                         NamedType *namedTy, | 
					
						
							|  |  |  |                                         Class *klass) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // ### todo handle index expressions.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<Scope *> scopes; | 
					
						
							|  |  |  |     _context.expand(klass->members(), _context.visibleScopes(), &scopes); | 
					
						
							|  |  |  |     QList<Result> results; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Name *memberName = control()->operatorNameId(OperatorNameId::ArrayAccessOp); | 
					
						
							|  |  |  |     QList<Symbol *> candidates = _context.resolve(memberName, scopes); | 
					
						
							|  |  |  |     foreach (Symbol *candidate, candidates) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = candidate->type(); | 
					
						
							|  |  |  |         Name *unqualifiedNameId = namedTy->name(); | 
					
						
							|  |  |  |         if (QualifiedNameId *q = namedTy->name()->asQualifiedNameId()) | 
					
						
							|  |  |  |             unqualifiedNameId = q->unqualifiedNameId(); | 
					
						
							|  |  |  |         if (TemplateNameId *templId = unqualifiedNameId->asTemplateNameId()) { | 
					
						
							|  |  |  |             Substitution subst; | 
					
						
							|  |  |  |             for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { | 
					
						
							|  |  |  |                 FullySpecifiedType templArgTy = templId->templateArgumentAt(i); | 
					
						
							|  |  |  |                 if (i < klass->templateParameterCount()) { | 
					
						
							|  |  |  |                     subst.append(qMakePair(klass->templateParameterAt(i)->name(), | 
					
						
							|  |  |  |                                            templArgTy)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Instantiation inst(control(), subst); | 
					
						
							|  |  |  |             ty = inst(ty); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const Result result(ty, candidate); | 
					
						
							|  |  |  |         if (! results.contains(result)) | 
					
						
							|  |  |  |             results.append(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return results; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ResolveExpression::visit(PostIncrDecrAST *) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | ResolveClass::ResolveClass() | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | QList<Symbol *> ResolveClass::operator()(NamedType *namedTy, | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                                                 ResolveExpression::Result p, | 
					
						
							|  |  |  |                                                 const LookupContext &context) | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const QList<ResolveExpression::Result> previousBlackList = _blackList; | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     const QList<Symbol *> symbols = resolveClass(namedTy, p, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  |     _blackList = previousBlackList; | 
					
						
							|  |  |  |     return symbols; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | QList<Symbol *> ResolveClass::operator()(ResolveExpression::Result p, | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  |                                                 const LookupContext &context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QList<ResolveExpression::Result> previousBlackList = _blackList; | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |     const QList<Symbol *> symbols = resolveClass(p, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  |     _blackList = previousBlackList; | 
					
						
							|  |  |  |     return symbols; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy, | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  |                                                          ResolveExpression::Result p, | 
					
						
							|  |  |  |                                                          const LookupContext &context) | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QList<Symbol *> resolvedSymbols; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_blackList.contains(p)) | 
					
						
							|  |  |  |         return resolvedSymbols; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _blackList.append(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QList<Symbol *> candidates = | 
					
						
							|  |  |  |             context.resolve(namedTy->name(), context.visibleScopes(p)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Symbol *candidate, candidates) { | 
					
						
							|  |  |  |         if (Class *klass = candidate->asClass()) { | 
					
						
							|  |  |  |             if (resolvedSymbols.contains(klass)) | 
					
						
							|  |  |  |                 continue; // we already know about `klass'
 | 
					
						
							|  |  |  |             resolvedSymbols.append(klass); | 
					
						
							|  |  |  |         } else if (candidate->isTypedef()) { | 
					
						
							|  |  |  |             if (Declaration *decl = candidate->asDeclaration()) { | 
					
						
							|  |  |  |                 if (Class *asClass = decl->type()->asClass()) { | 
					
						
							|  |  |  |                     // typedef struct { } Point;
 | 
					
						
							|  |  |  |                     // Point pt;
 | 
					
						
							|  |  |  |                     // pt.
 | 
					
						
							|  |  |  |                     resolvedSymbols.append(asClass); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     // typedef Point Boh;
 | 
					
						
							|  |  |  |                     // Boh b;
 | 
					
						
							|  |  |  |                     // b.
 | 
					
						
							|  |  |  |                     const ResolveExpression::Result r(decl->type(), decl); | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |                     resolvedSymbols += resolveClass(r, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (Declaration *decl = candidate->asDeclaration()) { | 
					
						
							|  |  |  |             if (Function *funTy = decl->type()->asFunction()) { | 
					
						
							|  |  |  |                 // QString foo("ciao");
 | 
					
						
							|  |  |  |                 // foo.
 | 
					
						
							|  |  |  |                 if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) { | 
					
						
							|  |  |  |                     const ResolveExpression::Result r(funTy->returnType(), decl); | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |                     resolvedSymbols += resolveClass(r, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return resolvedSymbols; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | QList<Symbol *> ResolveClass::resolveClass(ResolveExpression::Result p, | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  |                                                          const LookupContext &context) | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     FullySpecifiedType ty = p.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |         return resolveClass(namedTy, p, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |     } else if (ReferenceType *refTy = ty->asReferenceType()) { | 
					
						
							|  |  |  |         const ResolveExpression::Result e(refTy->elementType(), p.second); | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  |         return resolveClass(e, context); | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return QList<Symbol *>(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |