| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Licensees holding valid Qt Commercial licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the Qt Commercial License Agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Nokia. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							|  |  |  | ** General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ** packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** If you are unsure which license is appropriate for your use, please | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** contact the sales department at http://www.qtsoftware.com/contact.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +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>
 | 
					
						
							| 
									
										
										
										
											2009-05-19 13:24:20 +02:00
										 |  |  | #include <QtCore/QVarLengthArray>
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | #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) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-05-19 13:24:20 +02:00
										 |  |  |         if (TemplateNameId *t = name->asTemplateNameId()) { | 
					
						
							|  |  |  |             QVarLengthArray<FullySpecifiedType, 8> args(t->templateArgumentCount()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (unsigned i = 0; i < t->templateArgumentCount(); ++i) | 
					
						
							|  |  |  |                 args[i] = subst(t->templateArgumentAt(i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             TemplateNameId *n = _control->templateNameId(t->identifier(), | 
					
						
							|  |  |  |                                                          args.data(), args.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return FullySpecifiedType(_control->namedType(n)); | 
					
						
							|  |  |  |         } else if (name->isQualifiedNameId()) { | 
					
						
							|  |  |  |             // ### implement me
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         for (int i = 0; i < _substitution.size(); ++i) { | 
					
						
							|  |  |  |             const QPair<Name *, FullySpecifiedType> s = _substitution.at(i); | 
					
						
							|  |  |  |             if (name->isEqualTo(s.first)) | 
					
						
							|  |  |  |                 return s.second; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-19 13:24:20 +02:00
										 |  |  |         return FullySpecifiedType(_control->namedType(name)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							| 
									
										
										
										
											2009-05-19 13:24:20 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         Name *name = ty->name(); | 
					
						
							|  |  |  |         _type.setType(subst(name).type()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(Function *ty) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Name *name = ty->name(); | 
					
						
							|  |  |  |         FullySpecifiedType returnType = subst(ty->returnType()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Function *fun = _control->newFunction(0, name); | 
					
						
							|  |  |  |         fun->setScope(ty->scope()); | 
					
						
							| 
									
										
										
										
											2009-05-19 13:35:18 +02:00
										 |  |  |         fun->setConst(ty->isConst()); | 
					
						
							|  |  |  |         fun->setVolatile(ty->isVolatile()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     addResult(sem.check(ast->type_id, _context.expressionDocument()->globalSymbols())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     addResult(sem.check(ast->type_id, _context.expressionDocument()->globalSymbols())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 17:07:47 +02:00
										 |  |  | bool ResolveExpression::visit(NumericLiteralAST *ast) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-10 17:07:47 +02:00
										 |  |  |     Type *type = 0; | 
					
						
							|  |  |  |     NumericLiteral *literal = numericLiteral(ast->literal_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (literal->isChar()) | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::Char); | 
					
						
							|  |  |  |     else if (literal->isWideChar()) | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::WideChar); | 
					
						
							|  |  |  |     else if (literal->isInt()) | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::Int); | 
					
						
							|  |  |  |     else if (literal->isLong()) | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::Long); | 
					
						
							|  |  |  |     else if (literal->isLongLong()) | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::LongLong); | 
					
						
							|  |  |  |     else if (literal->isFloat()) | 
					
						
							|  |  |  |         type = control()->floatType(FloatType::Float); | 
					
						
							|  |  |  |     else if (literal->isDouble()) | 
					
						
							|  |  |  |         type = control()->floatType(FloatType::Double); | 
					
						
							|  |  |  |     else if (literal->isLongDouble()) | 
					
						
							|  |  |  |         type = control()->floatType(FloatType::LongDouble); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         type = control()->integerType(IntegerType::Int); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FullySpecifiedType ty(type); | 
					
						
							|  |  |  |     if (literal->isUnsigned()) | 
					
						
							|  |  |  |         ty.setUnsigned(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-13 16:03:46 +01:00
										 |  |  | bool ResolveExpression::visit(CompoundLiteralAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     accept(ast->type_id); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | bool ResolveExpression::visit(QualifiedNameAST *ast) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-31 10:57:27 +01:00
										 |  |  |     ResolveClass resolveClass; | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     Name *name = ast->name; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QList<Symbol *> symbols = _context.resolve(name); | 
					
						
							|  |  |  |     foreach (Symbol *symbol, symbols) { | 
					
						
							|  |  |  |         if (symbol->isTypedef()) { | 
					
						
							|  |  |  |             if (NamedType *namedTy = symbol->type()->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2008-12-30 11:54:42 +01:00
										 |  |  |                 const Result r(namedTy, symbol); | 
					
						
							| 
									
										
										
										
											2008-12-31 10:57:27 +01:00
										 |  |  |                 const QList<Symbol *> resolvedClasses = | 
					
						
							|  |  |  |                         resolveClass(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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     QList<Symbol *> symbols = _context.resolve(ast->name); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     QList<Symbol *> symbols = _context.resolve(ast->name); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     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) { | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |         if (Function *funTy = p.first->asFunctionType()) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             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); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |         } else if (Class *classTy = p.first->asClassType()) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             // 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) { | 
					
						
							| 
									
										
										
										
											2008-12-31 10:57:27 +01:00
										 |  |  |                 const QList<Result> overloads = | 
					
						
							|  |  |  |                         resolveArrayOperator(p, namedTy, classObject->asClass()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 foreach (Result r, overloads) { | 
					
						
							|  |  |  |                     FullySpecifiedType ty = r.first; | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |                     Function *funTy = ty->asFunctionType(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     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.
 | 
					
						
							| 
									
										
										
										
											2009-06-17 11:11:21 +02:00
										 |  |  |     Name *memberName = 0; | 
					
						
							|  |  |  |     if (ast->member_name) | 
					
						
							|  |  |  |         memberName = ast->member_name->name; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 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()) { | 
					
						
							| 
									
										
										
										
											2009-06-10 14:45:27 +02:00
										 |  |  |                 resolveClass.setPointerAccess(true); | 
					
						
							|  |  |  |                 QList<Symbol *> classObjectCandidates = resolveClass(namedTy, p, _context); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 foreach (Symbol *classObject, classObjectCandidates) { | 
					
						
							| 
									
										
										
										
											2009-06-10 14:45:27 +02:00
										 |  |  |                     results += resolveMember(p, memberName, | 
					
						
							|  |  |  |                                              control()->namedType(classObject->name()), // ### remove the call to namedType
 | 
					
						
							|  |  |  |                                              classObject->asClass()); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (classObjectCandidates.isEmpty()) { | 
					
						
							|  |  |  |                     resolveClass.setPointerAccess(false); | 
					
						
							|  |  |  |                     classObjectCandidates = resolveClass(namedTy, p, _context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     foreach (Symbol *classObject, classObjectCandidates) { | 
					
						
							|  |  |  |                         const QList<Result> overloads = resolveArrowOperator(p, namedTy, | 
					
						
							|  |  |  |                                                                              classObject->asClass()); | 
					
						
							|  |  |  |                         foreach (Result r, overloads) { | 
					
						
							|  |  |  |                             FullySpecifiedType ty = r.first; | 
					
						
							|  |  |  |                             Function *funTy = ty->asFunctionType(); | 
					
						
							|  |  |  |                             if (! funTy) | 
					
						
							|  |  |  |                                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                             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); | 
					
						
							|  |  |  |                             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } 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); | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |             else if (Function *fun = ty->asFunctionType()) { | 
					
						
							| 
									
										
										
										
											2009-07-09 16:20:20 +02:00
										 |  |  |                 if (fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope())) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     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() | 
					
						
							| 
									
										
										
										
											2009-06-10 14:45:27 +02:00
										 |  |  |     : _pointerAccess(false) | 
					
						
							| 
									
										
										
										
											2008-12-29 12:26:02 +01:00
										 |  |  | { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-10 14:45:27 +02:00
										 |  |  | bool ResolveClass::pointerAccess() const | 
					
						
							|  |  |  | { return _pointerAccess; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResolveClass::setPointerAccess(bool pointerAccess) | 
					
						
							|  |  |  | { _pointerAccess = pointerAccess; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 12:03:49 +01:00
										 |  |  | QList<Symbol *> ResolveClass::operator()(NamedType *namedTy, | 
					
						
							| 
									
										
										
										
											2008-12-31 10:57:27 +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-31 10:57:27 +01:00
										 |  |  |                                          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(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-31 10:57:27 +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()) { | 
					
						
							| 
									
										
										
										
											2009-06-10 14:45:27 +02:00
										 |  |  |                 if (_pointerAccess && decl->type()->isPointerType()) { | 
					
						
							|  |  |  |                     PointerType *ptrTy = decl->type()->asPointerType(); | 
					
						
							|  |  |  |                     _pointerAccess = false; | 
					
						
							|  |  |  |                     const ResolveExpression::Result r(ptrTy->elementType(), decl); | 
					
						
							|  |  |  |                     resolvedSymbols += resolveClass(r, context); | 
					
						
							|  |  |  |                     _pointerAccess = true; | 
					
						
							|  |  |  |                 } else if (Class *asClass = decl->type()->asClassType()) { | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                     // 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()) { | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |             if (Function *funTy = decl->type()->asFunctionType()) { | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                 // QString foo("ciao");
 | 
					
						
							|  |  |  |                 // foo.
 | 
					
						
							| 
									
										
										
										
											2009-07-09 16:20:20 +02:00
										 |  |  |                 if (funTy->scope() && (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope())) { | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |                     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-31 10:57:27 +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 *>(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |