~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to languages/cpp/cppduchain/typeconversion.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
 
3
 
 
4
   This library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Library General Public
 
6
   License version 2 as published by the Free Software Foundation.
 
7
 
 
8
   This library is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
   Library General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU Library General Public License
 
14
   along with this library; see the file COPYING.LIB.  If not, write to
 
15
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
16
   Boston, MA 02110-1301, USA.
 
17
*/
 
18
 
 
19
#include "typeconversion.h"
 
20
#include "cppduchain/typeutils.h"
 
21
#include "cppduchain/cpptypes.h"
 
22
#include "overloadresolution.h"
 
23
#include <language/duchain/ducontext.h>
 
24
#include <language/duchain/topducontext.h>
 
25
#include <typeinfo>
 
26
#include <language/duchain/duchainlock.h>
 
27
#include <language/duchain/duchain.h>
 
28
#include <qthread.h>
 
29
#include <language/duchain/classfunctiondeclaration.h>
 
30
#include <language/duchain/types/typeutils.h>
 
31
 
 
32
 
 
33
using namespace Cpp;
 
34
using namespace KDevelop;
 
35
using namespace TypeUtils;
 
36
 
 
37
struct ImplicitConversionParams {
 
38
  IndexedType from, to;
 
39
  bool fromLValue, noUserDefinedConversion;
 
40
  
 
41
  bool operator==(const ImplicitConversionParams& rhs) const {
 
42
    return from == rhs.from && to == rhs.to && fromLValue == rhs.fromLValue && noUserDefinedConversion == rhs.noUserDefinedConversion;
 
43
  }
 
44
};
 
45
 
 
46
uint qHash(const ImplicitConversionParams& params) {
 
47
  return (params.from.hash() * 36109 + params.to.hash()) * (params.fromLValue ? 111 : 53) * (params.noUserDefinedConversion ? 317293 : 1);
 
48
}
 
49
 
 
50
namespace Cpp {
 
51
class TypeConversionCache
 
52
{
 
53
public:
 
54
 
 
55
    QHash<ImplicitConversionParams, int> m_implicitConversionResults;
 
56
/*    QHash<QPair<IndexedType, IndexedType>, uint> m_standardConversionResults;
 
57
    QHash<QPair<IndexedType, IndexedType>, uint> m_userDefinedConversionResults;*/
 
58
//     QHash<QPair<IndexedType, IndexedType>, bool> m_isPublicBaseCache;
 
59
};
 
60
}
 
61
 
 
62
QHash<Qt::HANDLE, TypeConversionCache*> typeConversionCaches;
 
63
QMutex typeConversionCacheMutex;
 
64
 
 
65
void TypeConversion::startCache() {
 
66
  QMutexLocker lock(&typeConversionCacheMutex);
 
67
  if(!typeConversionCaches.contains(QThread::currentThreadId()))
 
68
    typeConversionCaches[QThread::currentThreadId()] = new TypeConversionCache;
 
69
}
 
70
 
 
71
void TypeConversion::stopCache() {
 
72
  QMutexLocker lock(&typeConversionCacheMutex);
 
73
  if(typeConversionCaches.contains(QThread::currentThreadId())) {
 
74
    delete typeConversionCaches[QThread::currentThreadId()];
 
75
    typeConversionCaches.remove(QThread::currentThreadId());
 
76
  }
 
77
}
 
78
 
 
79
TypeConversion::TypeConversion(const TopDUContext* topContext) : m_topContext(topContext) {
 
80
 
 
81
  QMutexLocker lock(&typeConversionCacheMutex);
 
82
  QHash<Qt::HANDLE, TypeConversionCache*>::iterator it = typeConversionCaches.find(QThread::currentThreadId());
 
83
  if(it != typeConversionCaches.end())
 
84
    m_cache = *it;
 
85
  else
 
86
    m_cache = 0;
 
87
}
 
88
 
 
89
 
 
90
TypeConversion::~TypeConversion() {
 
91
}
 
92
 
 
93
/**
 
94
 * All information taken from iso c++ draft
 
95
 *
 
96
 * Standard-conversion-sequence:
 
97
 *  - zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, function-to-pointer conversion
 
98
 *  - zero or one conversion from the following set: integral promotions, floating point promotions, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
 
99
 *
 
100
 * Standard-conversion-sequence will be applied to expression when it  needs to be converted to another type.
 
101
 *
 
102
 * Note: lvalue = reference to existing object
 
103
 *       rvalue = copied object
 
104
 *
 
105
 * When is an expression implicitly converted? :
 
106
 *  - When used as operands of operators.
 
107
 *  - When used in a condition statement(destination type is bool)
 
108
 *  - When used in the expression of a switch statement
 
109
 *  - When used as the source expression for an initialization(includes argument in function-call and return-statement)
 
110
 *
 
111
 * User-defined conversions:
 
112
 *  - Constructors and conversion-functions.
 
113
 *  - At most one such conversion is applied when doing implicit type-conversion
 
114
 * */
 
115
 
 
116
/**
 
117
 * An implicit conversion-sequence is one of the following:
 
118
 *  - a standard conversion sequence
 
119
 *  - a user-defined conversion sequence
 
120
 *  - an ellipsis conversion sequence
 
121
 *
 
122
 * */
 
123
uint TypeConversion::implicitConversion( IndexedType _from, IndexedType _to, bool fromLValue, bool noUserDefinedConversion ) {
 
124
  m_baseConversionLevels = 0;
 
125
 
 
126
  int conv = 0;
 
127
  
 
128
  ImplicitConversionParams params;
 
129
  params.from = _from;
 
130
  params.to = _to;
 
131
  params.fromLValue = fromLValue;
 
132
  params.noUserDefinedConversion = noUserDefinedConversion;
 
133
  
 
134
  if(m_cache) {
 
135
    QHash<ImplicitConversionParams, int>::const_iterator it = m_cache->m_implicitConversionResults.constFind(params);
 
136
    if(it != m_cache->m_implicitConversionResults.constEnd())
 
137
      return *it;
 
138
  }
 
139
  
 
140
  AbstractType::Ptr to = unAliasedType(_to.abstractType());
 
141
  AbstractType::Ptr from = unAliasedType(_from.abstractType());
 
142
  
 
143
  if( !from || !to ) {
 
144
    problem( from, to, "one type is invalid" );
 
145
    goto ready;
 
146
  }else{
 
147
    
 
148
    //kDebug(9007) << "Checking conversion from " << from->toString() << " to " << to->toString();
 
149
    ReferenceType::Ptr fromReference = from.cast<ReferenceType>();
 
150
    if( fromReference )
 
151
      fromLValue = true;
 
152
 
 
153
    ///iso c++ draft 13.3.3.1.4 reference-binding, modeled roughly
 
154
    ReferenceType::Ptr toReference = to.cast<ReferenceType>();
 
155
    if( toReference ) {
 
156
      AbstractType::Ptr realFrom = realType(from, m_topContext);
 
157
      AbstractType::Ptr realTo = realType(to, m_topContext);
 
158
      if(!realFrom || !realTo) {
 
159
        problem( from, to, "one type is invalid" );
 
160
        goto ready;
 
161
      }
 
162
      if( fromLValue && ((realTo->modifiers() & AbstractType::ConstModifier) || (realTo->modifiers() & AbstractType::ConstModifier) == isConstant(from)) ) {
 
163
        ///Since from is an lvalue, and the constant-specification matches, we can maybe directly create a reference
 
164
        //Either identity-conversion:
 
165
        if( identityConversion( realFrom, realTo ) ) {
 
166
          conv = ExactMatch + 2*ConversionRankOffset;
 
167
          goto ready;
 
168
        }
 
169
        //Or realType(toReference) is a public base-class of realType(fromReference)
 
170
        CppClassType::Ptr fromClass = realFrom.cast<CppClassType>();
 
171
        CppClassType::Ptr toClass = realTo.cast<CppClassType>();
 
172
 
 
173
        if( fromClass && toClass && isPublicBaseClass( fromClass, toClass, m_topContext, &m_baseConversionLevels ) ) {
 
174
          conv = ExactMatch + 2*ConversionRankOffset;
 
175
          goto ready;
 
176
        }
 
177
      }
 
178
 
 
179
      //We cannot directly create a reference, but maybe there is a user-defined conversion that creates a compatible reference, as in iso c++ 13.3.3.1.4.1
 
180
      if( !noUserDefinedConversion ) {
 
181
        if( int rank = userDefinedConversion( from, to, fromLValue, true ) ) {
 
182
          conv = rank + ConversionRankOffset;
 
183
          goto ready;
 
184
        }
 
185
      }
 
186
 
 
187
      if( realTo->modifiers() & AbstractType::ConstModifier ) {
 
188
        //For constant references, the compiler can create a temporary object holding the converted value. So just forget whether the types are references.
 
189
        conv = implicitConversion( realType(from, m_topContext)->indexed(), realType(to, m_topContext)->indexed(), fromLValue, noUserDefinedConversion );
 
190
        goto ready;
 
191
      }
 
192
    }
 
193
 
 
194
    {
 
195
      int tempConv = 0;
 
196
 
 
197
      //This is very simplified, see iso c++ draft 13.3.3.1
 
198
 
 
199
      if( (tempConv = standardConversion(from,to)) ) {
 
200
        tempConv += 2*ConversionRankOffset;
 
201
        if( tempConv > conv )
 
202
          conv = tempConv;
 
203
      }
 
204
 
 
205
      if( !noUserDefinedConversion ) {
 
206
        if( (tempConv = userDefinedConversion(from, to, fromLValue)) ) {
 
207
          tempConv += ConversionRankOffset;
 
208
          if( tempConv > conv )
 
209
            conv = tempConv;
 
210
        }
 
211
      }
 
212
      
 
213
      if( (tempConv = ellipsisConversion(from, to)) && tempConv > conv )
 
214
        conv = tempConv;
 
215
    }
 
216
  }
 
217
 
 
218
  ready:
 
219
  
 
220
  if(m_cache)
 
221
    m_cache->m_implicitConversionResults.insert(params, conv);
 
222
  
 
223
  return conv;
 
224
}
 
225
 
 
226
int TypeConversion::baseConversionLevels() const {
 
227
  return m_baseConversionLevels;
 
228
}
 
229
 
 
230
///Helper for standardConversion(..) that makes sure that when one category is taken out of the possible ones, the earlier are taken out too, because categories must be checked in order.
 
231
  int removeCategories( int categories, ConversionCategories remove ) {
 
232
    for( int a = 1; a <= remove; a*=2 ) {
 
233
      categories &= ~a;
 
234
    }
 
235
    return categories;
 
236
  }
 
237
 
 
238
  ///if myRank is better than rank, rank will be set to myRank
 
239
  void maximizeRank( ConversionRank& rank, ConversionRank myRank ) {
 
240
    if( myRank > rank )
 
241
      rank = myRank;
 
242
  }
 
243
 
 
244
  ///Returns the worse of the both given ranks
 
245
  ConversionRank worseRank( ConversionRank rank1, ConversionRank rank2 ) {
 
246
    return rank1 > rank2 ? rank2 : rank1;
 
247
  }
 
248
  
 
249
ConversionRank TypeConversion::pointerConversion( PointerType::Ptr from, PointerType::Ptr to ) {
 
250
  
 
251
  //We can convert non-const -> const, but not const -> non-const
 
252
//   if(to->modifiers() & AbstractType::ConstModifier || !(from->modifiers()& AbstractType::ConstModifier)) {
 
253
 
 
254
    if(!from || !to)
 
255
      return NoMatch;
 
256
 
 
257
    AbstractType::Ptr nextFrom = unAliasedType(from->baseType());
 
258
    AbstractType::Ptr nextTo = unAliasedType(to->baseType());
 
259
 
 
260
    if(!nextTo || !nextFrom)
 
261
      return NoMatch;
 
262
 
 
263
    if((nextFrom->modifiers() & AbstractType::ConstModifier) && !(nextTo->modifiers() & AbstractType::ConstModifier))
 
264
      return NoMatch; //Cannot convert const -> non-const
 
265
    
 
266
    PointerType::Ptr pointerFrom = nextFrom.cast<PointerType>();
 
267
    PointerType::Ptr pointerTo = nextTo.cast<PointerType>();
 
268
    if(pointerFrom && pointerTo)
 
269
      return pointerConversion(pointerFrom, pointerTo);
 
270
    
 
271
    CppClassType::Ptr fromClass = nextFrom.cast<CppClassType>();
 
272
    CppClassType::Ptr toClass = nextTo.cast<CppClassType>();
 
273
    if( toClass && fromClass )
 
274
      if(toClass->modifiers() & AbstractType::ConstModifier || !(fromClass->modifiers()& AbstractType::ConstModifier))
 
275
        if( isPublicBaseClass( fromClass, toClass, m_topContext, &m_baseConversionLevels ) )
 
276
          return ((toClass->modifiers() & AbstractType::ConstModifier) != (fromClass->modifiers() & AbstractType::ConstModifier)) ? Conversion : ExactMatch;
 
277
    
 
278
    bool changed = false;
 
279
    //Change the constness matches, so they are equal if compatible
 
280
    if(nextTo->modifiers() & AbstractType::ConstModifier) {
 
281
      nextFrom->setModifiers(nextFrom->modifiers() | AbstractType::ConstModifier);
 
282
      changed = true;
 
283
    }
 
284
    
 
285
    if(identityConversion(nextFrom, nextTo))
 
286
      return changed ? Conversion : ExactMatch;
 
287
    
 
288
//   }
 
289
  
 
290
  return NoMatch;
 
291
}
 
292
 
 
293
/**
 
294
 *
 
295
 *
 
296
 **/
 
297
ConversionRank TypeConversion::standardConversion( AbstractType::Ptr from, AbstractType::Ptr to, int categories, int maxCategories ) {
 
298
 
 
299
  /** Lowest conversion-rank of all sub-conversions is returned
 
300
   * See iso c++ draft 13.3.3.1.1
 
301
   *
 
302
   * Conversions from up to 3 different categories are allowed
 
303
   *
 
304
   * Table about category and rank:
 
305
   *
 
306
   * Conversion                       Category                  Rank                   iso c++ clause
 
307
   * -----------------------------------------------------------------------------------------------------
 
308
   * No conversion                    Identity                  Exact Match
 
309
   * Lvalue-to-rvalue conv.           Lvalue Transformation     Exact Match            4.1
 
310
   * Array-to-pointer conv.           Lvalue Transformation     Exact Match            4.2
 
311
   * Function-to-pointer conv.        Lvalue Transformation     Exact Match            4.3
 
312
   * Qualification conversion         Qualification Adjustment  Exact Match            4.4
 
313
   * Integral promotions              Promotion                 Promotion              4.5
 
314
   * Floating point promotion         Promotion                 Promotion              4.6
 
315
   * Integral conversions             Conversion                Conversion             4.7
 
316
   * Floating point conversions       Conversion                Conversion             4.8
 
317
   * Floating-integral conversions    Conversion                Conversion             4.9
 
318
   * Pointer conversions              Conversion                Conversion             4.10
 
319
   * Pointer to member conversions    Conversion                Conversion             4.11
 
320
   * Boolean conversions              Conversion                Conversion             4.12
 
321
   *
 
322
   * A standard-conversion may consist of up to 3 conversions from different categories
 
323
   *
 
324
   *
 
325
   * This function achieves the rules recursively. Performance-wise that may not be perfect, because sometimes many different paths can are followed.
 
326
   **/
 
327
  from = unAliasedType(from);
 
328
  to = unAliasedType(to);
 
329
 
 
330
  if( (categories & IdentityCategory) && identityConversion( from, to ) )
 
331
    return ExactMatch;
 
332
 
 
333
  if(!from || !to)
 
334
    return NoMatch;
 
335
  
 
336
  ConversionRank bestRank = NoMatch;
 
337
 
 
338
  ///Try lvalue-transformation category
 
339
  if( (categories & LValueTransformationCategory) ) {
 
340
 
 
341
    bool constRef = false;
 
342
    if( isReferenceType(from) ) {
 
343
      ///Transform lvalue to rvalue. Iso c++ draft 4.1 modeled roughly
 
344
      
 
345
      AbstractType::Ptr fromNonConstant = realType(from, m_topContext)->indexed().abstractType();
 
346
 
 
347
      //When copying, the type becomes non-constant
 
348
      if(fromNonConstant && fromNonConstant->modifiers() & AbstractType::ConstModifier)
 
349
        fromNonConstant->setModifiers(fromNonConstant->modifiers() & ~(AbstractType::ConstModifier));
 
350
      
 
351
      ConversionRank ret = standardConversion( fromNonConstant, to, removeCategories(categories,LValueTransformationCategory), maxCategories-1 );
 
352
      maximizeRank( bestRank, ret );
 
353
    }else if( ArrayType::Ptr array = realType(from, m_topContext, &constRef).cast<ArrayType>() ) { //realType(from) is used here so reference-to-array can be transformed to a pointer. This does not exactly follow the standard I think, check that.
 
354
      ///Transform array to pointer. Iso c++ draft 4.2 modeled roughly.
 
355
      PointerType::Ptr p( new PointerType() );
 
356
      if (constRef)
 
357
        p->setModifiers(AbstractType::ConstModifier);
 
358
      p->setBaseType(array->elementType());
 
359
      ConversionRank rank = standardConversion( p.cast<AbstractType>(), to, removeCategories(categories,LValueTransformationCategory), maxCategories-1 );
 
360
 
 
361
      maximizeRank( bestRank, worseRank(rank, ExactMatch ) );
 
362
    } else if( FunctionType::Ptr function = realType(from, m_topContext, &constRef).cast<FunctionType>() ) {
 
363
      ///Transform lvalue-function. Iso c++ draft 4.3
 
364
      //This code is nearly the same as the above array-to-pointer conversion. Maybe it should be merged.
 
365
 
 
366
      PointerType::Ptr p( new PointerType() );
 
367
      if (constRef)
 
368
        p->setModifiers(AbstractType::ConstModifier);
 
369
      p->setBaseType( function.cast<AbstractType>() );
 
370
 
 
371
      ConversionRank rank = standardConversion( p.cast<AbstractType>(), to, removeCategories(categories,LValueTransformationCategory), maxCategories-1 );
 
372
 
 
373
      maximizeRank( bestRank, worseRank(rank, ExactMatch ) );
 
374
    }else if(from->modifiers() & AbstractType::ConstModifier) {
 
375
      ///We can transform a constant lvalue to a non-constant rvalue
 
376
      AbstractType::Ptr fromNonConstant = from->indexed().abstractType();
 
377
      fromNonConstant->setModifiers(fromNonConstant->modifiers() & ~(AbstractType::ConstModifier));
 
378
      ConversionRank ret = standardConversion( fromNonConstant, to, removeCategories(categories,LValueTransformationCategory), maxCategories-1 );
 
379
      maximizeRank( bestRank, ret );
 
380
    }
 
381
  }
 
382
 
 
383
//   if( categories & QualificationAdjustmentCategory ) {
 
384
//     PointerType::Ptr pnt = from.cast<PointerType>();
 
385
// 
 
386
//     ///@todo iso c++ 4.4.2 etc: pointer to member
 
387
//   }
 
388
 
 
389
  EnumerationType::Ptr toEnumeration = to.cast<EnumerationType>();
 
390
 
 
391
  if(toEnumeration) {
 
392
    //Eventually convert enumerator -> enumeration if the enumeration equals
 
393
    EnumeratorType::Ptr fromEnumerator = from.cast<EnumeratorType>();
 
394
    if(fromEnumerator) {
 
395
      Declaration* enumeratorDecl = fromEnumerator->declaration(m_topContext);
 
396
      Declaration* enumerationDecl = toEnumeration->declaration(m_topContext);
 
397
      if(enumeratorDecl && enumerationDecl && enumeratorDecl->context()->owner() == enumerationDecl)
 
398
        return ExactMatch; //Converting an enumeration value into its own enumerator type, perfect match.
 
399
    }
 
400
    ///iso c++ 7.2.9: No conversion or promotion to enumerator types is possible
 
401
    return bestRank;
 
402
  }
 
403
 
 
404
  if( categories & PromotionCategory ) {
 
405
 
 
406
    IntegralType::Ptr integral = from.cast<IntegralType>();
 
407
    if( integral ) {
 
408
 
 
409
      ///Integral promotions, iso c++ 4.5
 
410
      if( integerConversionRank(integral) < unsignedIntConversionRank && integral->dataType() != IntegralType::TypeBoolean && integral->dataType() != IntegralType::TypeWchar_t && integral->dataType() != IntegralType::TypeVoid ) {
 
411
        ///iso c++ 4.5.1
 
412
        ///@todo re-create a mini repository for fast lookup of such integral types, so we don't have to do allocations here
 
413
        AbstractType::Ptr newFrom( new IntegralType(IntegralType::TypeInt) );
 
414
        newFrom->setModifiers((integral->modifiers() & AbstractType::UnsignedModifier) ? AbstractType::UnsignedModifier : AbstractType::NoModifiers);
 
415
        ConversionRank rank = standardConversion( newFrom, to, removeCategories(categories,PromotionCategory), maxCategories-1 );
 
416
 
 
417
        maximizeRank( bestRank, worseRank(rank, Promotion ) );
 
418
      }
 
419
 
 
420
      ///Floating point promotion, iso c++ 4.6
 
421
      if( integral->dataType() == IntegralType::TypeDouble ) {
 
422
        AbstractType::Ptr newFrom( new IntegralType(IntegralType::TypeDouble) );
 
423
        ConversionRank rank = standardConversion( newFrom, to, removeCategories(categories,PromotionCategory), maxCategories-1 );
 
424
 
 
425
        maximizeRank( bestRank, worseRank(rank, Promotion ) );
 
426
      }
 
427
    }
 
428
  }
 
429
 
 
430
  if( categories & ConversionCategory )
 
431
  {
 
432
    IntegralType::Ptr fromIntegral = from.cast<IntegralType>();
 
433
    EnumerationType::Ptr fromEnumeration = fromIntegral.cast<EnumerationType>();
 
434
    EnumeratorType::Ptr fromEnumerator = fromIntegral.cast<EnumeratorType>();
 
435
 
 
436
    IntegralType::Ptr toIntegral = to.cast<IntegralType>();
 
437
 
 
438
    if( fromIntegral && toIntegral ) {
 
439
      ///iso c++ 4.7 integral conversion: we can convert from any integer type to any other integer type, and from enumeration-type to integer-type
 
440
      if( (fromEnumeration || fromEnumerator || isIntegerType(fromIntegral)) && isIntegerType(toIntegral) )
 
441
      {
 
442
        maximizeRank( bestRank, Conversion );
 
443
      }
 
444
 
 
445
      ///iso c++ 4.8 floating point conversion: any floating-point to any other floating-point
 
446
      if( isFloatingPointType(fromIntegral) && isFloatingPointType(toIntegral) )
 
447
      {
 
448
        maximizeRank( bestRank, Conversion );
 
449
      }
 
450
 
 
451
      ///iso c++ 4.9 floating-integral conversion: floating point can be converted to integral, enumeration and integral can be converted to floating point
 
452
      if( ( ( fromEnumeration || fromEnumerator || isIntegerType(fromIntegral) ) && isFloatingPointType(toIntegral) ) ||
 
453
          ( isFloatingPointType(fromIntegral) && isIntegerType(toIntegral) ) )
 
454
      {
 
455
 
 
456
        maximizeRank( bestRank, Conversion );
 
457
      }
 
458
    }
 
459
 
 
460
    ///iso c++ 4.10 pointer conversion: null-type con be converted to pointer
 
461
    PointerType::Ptr fromPointer = from.cast<PointerType>();
 
462
    PointerType::Ptr toPointer = to.cast<PointerType>();
 
463
 
 
464
    if( isNullType(from) && toPointer )
 
465
    {
 
466
        maximizeRank( bestRank, Conversion );
 
467
    }
 
468
 
 
469
    ///Pointer can be converted to void*
 
470
    if( fromPointer && toPointer && isVoidType(toPointer->baseType()) )
 
471
    {
 
472
        maximizeRank( bestRank, Conversion );
 
473
    }
 
474
 
 
475
    ///iso c++ 4.10.3 - class-pointer conversion
 
476
    if( fromPointer && toPointer /*&& fromPointer->cv() == toPointer->cv()*/ )
 
477
      maximizeRank( bestRank, pointerConversion(fromPointer, toPointer) );
 
478
 
 
479
    ///@todo pointer-to-member conversion
 
480
 
 
481
    ///iso c++ 4.12 Boolean conversions
 
482
    if( toIntegral && toIntegral->dataType() == IntegralType::TypeBoolean ) {
 
483
      //We are converting to a boolean value
 
484
      if( fromPointer || fromEnumeration || fromEnumerator || (fromIntegral && (isIntegerType(fromIntegral) || isFloatingPointType(fromIntegral))) ) {
 
485
        maximizeRank( bestRank, Conversion );
 
486
      }
 
487
    }
 
488
  }
 
489
 
 
490
  return bestRank;
 
491
}
 
492
 
 
493
bool TypeConversion::identityConversion( AbstractType::Ptr from, AbstractType::Ptr to ) {
 
494
  
 
495
  from = TypeUtils::unAliasedType(from);
 
496
  to = TypeUtils::unAliasedType(to);
 
497
  
 
498
  if( !from && !to )
 
499
    return true;
 
500
  else if( !from || !to )
 
501
    return false;
 
502
 
 
503
  //ConstantIntegralType::equals does not return true on equals in this case, but the type is compatible.
 
504
  if(from.cast<ConstantIntegralType>() && typeid(*to) == typeid(IntegralType))
 
505
    return true;
 
506
 
 
507
  return from->equals(to.unsafeData());
 
508
}
 
509
 
 
510
void TypeConversion::problem( AbstractType::Ptr from, AbstractType::Ptr to, const QString& desc ) {
 
511
  Q_UNUSED(from)
 
512
  Q_UNUSED(to)
 
513
  Q_UNUSED(desc)
 
514
}
 
515
 
 
516
ConversionRank TypeConversion::userDefinedConversion( AbstractType::Ptr from, AbstractType::Ptr to, bool fromLValue, bool secondConversionIsIdentity ) {
 
517
  /**
 
518
   * Two possible cases:
 
519
   * - from is a class, that has a conversion-function
 
520
   * - to is a class that has a converting(non-explicit) matching constructor
 
521
   **/
 
522
  ConversionRank bestRank = NoMatch;
 
523
 
 
524
  bool fromConst = false;
 
525
  AbstractType::Ptr realFrom( realType(from, m_topContext, &fromConst) );
 
526
  CppClassType::Ptr fromClass = realFrom.cast<CppClassType>();
 
527
  {
 
528
    ///Try user-defined conversion using a conversion-function, iso c++ 12.3
 
529
 
 
530
    if( fromClass )
 
531
    {
 
532
      ///Search for a conversion-function that has a compatible output
 
533
      QHash<FunctionType::Ptr, ClassFunctionDeclaration*> conversionFunctions;
 
534
      getMemberFunctions(fromClass, m_topContext, conversionFunctions, "operator{...cast...}", fromConst);
 
535
 
 
536
      for( QHash<FunctionType::Ptr, ClassFunctionDeclaration*>::const_iterator it = conversionFunctions.constBegin(); it != conversionFunctions.constEnd(); ++it )
 
537
      {
 
538
        if(isAccessible(it.value())) {
 
539
          AbstractType::Ptr convertedType( it.key()->returnType() );
 
540
          ConversionRank rank = standardConversion( convertedType, to );
 
541
 
 
542
          if( rank != NoMatch && (!secondConversionIsIdentity || rank == ExactMatch) )
 
543
          {
 
544
            //We have found a matching conversion-function
 
545
            if( identityConversion(realType(convertedType, m_topContext), to) )
 
546
              maximizeRank( bestRank, ExactMatch );
 
547
            else
 
548
              maximizeRank( bestRank, Conversion );
 
549
          }
 
550
        }
 
551
      }
 
552
    }
 
553
  }
 
554
 
 
555
  AbstractType::Ptr realTo( realType(to, m_topContext) );
 
556
 
 
557
  {
 
558
    ///Try conversion using constructor
 
559
    CppClassType::Ptr toClass = realTo.cast<CppClassType>(); //@todo think whether the realType(..) is ok
 
560
    if( toClass && toClass->declaration(m_topContext) )
 
561
    {
 
562
      if( fromClass ) {
 
563
        if( isPublicBaseClass(fromClass, toClass, m_topContext, &m_baseConversionLevels ) ) {
 
564
          ///@todo check whether this is correct
 
565
          //There is a default-constructor in toClass that initializes from const toClass&, which fromClass can be converted to
 
566
          maximizeRank( bestRank, Conversion );
 
567
        }
 
568
      }
 
569
 
 
570
      DUContextPointer ptr(toClass->declaration(m_topContext)->logicalInternalContext(m_topContext));
 
571
      OverloadResolver resolver( ptr, TopDUContextPointer( const_cast<TopDUContext*>(m_topContext) ) );
 
572
      Declaration* function = resolver.resolveConstructor( OverloadResolver::Parameter( from, fromLValue ), true, true );
 
573
 
 
574
      if( function && isAccessible(dynamic_cast<ClassMemberDeclaration*>(function)) )
 
575
      {
 
576
        //We've successfully located an overloaded constructor that accepts the argument
 
577
          if( to == realFrom )
 
578
            maximizeRank( bestRank, ExactMatch );
 
579
          else
 
580
            maximizeRank( bestRank, Conversion );
 
581
      }
 
582
    }
 
583
  }
 
584
 
 
585
  return bestRank;
 
586
}
 
587
 
 
588
bool TypeConversion::isAccessible(const ClassMemberDeclaration* decl) {
 
589
  ///@todo Use Cpp::isAccessible here
 
590
  if(!decl)
 
591
    return false;
 
592
  return decl->accessPolicy() == Declaration::Public;
 
593
}
 
594
 
 
595
ConversionRank TypeConversion::ellipsisConversion( AbstractType::Ptr from, AbstractType::Ptr to ) {
 
596
  Q_UNUSED(from)
 
597
  Q_UNUSED(to)
 
598
  return NoMatch;
 
599
}
 
600