source: src/ResolvExpr/ConversionCost.cc @ 0d070ca

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 0d070ca was 0d070ca, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

disabled new heaptrace feature

  • Property mode set to 100644
File size: 40.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ConversionCost.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 07:06:19 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Jul 29 16:11:00 2020
13// Update Count     : 28
14//
15
16#include "ConversionCost.h"
17
18#include <cassert>                       // for assert
19#include <list>                          // for list, list<>::const_iterator
20#include <string>                        // for operator==, string
21
22#include "ResolvExpr/Cost.h"             // for Cost
23#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
24#include "SymTab/Indexer.h"              // for Indexer
25#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
26#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
27#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
28
29namespace ResolvExpr {
30#if 0
31        const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
32        const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
33        const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
34        const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
35        const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
36        const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
37        const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
38        const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
39        const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
40#endif
41
42#if 0
43#define PRINT(x) x
44#else
45#define PRINT(x)
46#endif
47
48        Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
49                        const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
50                if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
51                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
52                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
53                                if ( eqvClass->type ) {
54                                        return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
55                                } else {
56                                        return Cost::infinity;
57                                }
58                        } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
59                                PRINT( std::cerr << " found" << std::endl; )
60                                const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
61                                // all typedefs should be gone by this point
62                                assert( type );
63                                if ( type->base ) {
64                                        return conversionCost( src, type->base, srcIsLvalue, indexer, env )
65                                                + Cost::safe;
66                                } // if
67                        } // if
68                        PRINT( std::cerr << " not found" << std::endl; )
69                } // if
70                PRINT(
71                        std::cerr << "src is ";
72                        src->print( std::cerr );
73                        std::cerr << std::endl << "dest is ";
74                        dest->print( std::cerr );
75                        std::cerr << std::endl << "env is" << std::endl;
76                        env.print( std::cerr, 8 );
77                )
78                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
79                        PRINT( std::cerr << "compatible!" << std::endl; )
80                        return Cost::zero;
81                } else if ( dynamic_cast< const VoidType * >( dest ) ) {
82                        return Cost::safe;
83                } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
84                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
85                        return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
86                                return ptrsAssignable( t1, t2, env );
87                        });
88                } else {
89                        PassVisitor<ConversionCost> converter(
90                                dest, srcIsLvalue, indexer, env,
91                                (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
92                                        conversionCost );
93                        src->accept( converter );
94                        if ( converter.pass.get_cost() == Cost::infinity ) {
95                                return Cost::infinity;
96                        } else {
97                                return converter.pass.get_cost() + Cost::zero;
98                        } // if
99                } // if
100        }
101
102        static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
103                        int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
104                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
105                if ( diff > 0 ) {
106                        // TODO: document this
107                        Cost cost = convertToReferenceCost(
108                                strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
109                                diff-1, indexer, env, func );
110                        cost.incReference();
111                        return cost;
112                } else if ( diff < -1 ) {
113                        // TODO: document this
114                        Cost cost = convertToReferenceCost(
115                                src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
116                                diff+1, indexer, env, func );
117                        cost.incReference();
118                        return cost;
119                } else if ( diff == 0 ) {
120                        const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
121                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
122                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
123                                PRINT( std::cerr << "converting between references" << std::endl; )
124                                Type::Qualifiers tq1 = srcAsRef->base->tq;
125                                Type::Qualifiers tq2 = destAsRef->base->tq;
126                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
127                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
128                                        if ( tq1 == tq2 ) {
129                                                // types are the same
130                                                return Cost::zero;
131                                        } else {
132                                                // types are the same, except otherPointer has more qualifiers
133                                                return Cost::safe;
134                                        }
135                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
136                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
137                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
138                                        if ( assignResult > 0 ) {
139                                                return Cost::safe;
140                                        } else if ( assignResult < 0 ) {
141                                                return Cost::unsafe;
142                                        } // if
143                                } // if
144                        } else {
145                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
146                                PassVisitor<ConversionCost> converter(
147                                        dest, srcIsLvalue, indexer, env,
148                                        (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
149                                                conversionCost );
150                                src->accept( converter );
151                                return converter.pass.get_cost();
152                        } // if
153                } else {
154                        const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
155                        assert( diff == -1 && destAsRef );
156                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
157                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
158                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
159                                if ( srcIsLvalue ) {
160                                        PRINT(
161                                                std::cerr << "lvalue to reference conversion" << std::endl;
162                                                std::cerr << src << " => " << destAsRef << std::endl;
163                                        )
164                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
165                                        if ( src->tq == destAsRef->base->tq ) {
166                                                return Cost::reference; // cost needs to be non-zero to add cast
167                                        } if ( src->tq < destAsRef->base->tq ) {
168                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
169                                        } else {
170                                                return Cost::unsafe;
171                                        } // if
172                                } else if ( destAsRef->base->get_const() ) {
173                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
174                                        // rvalue-to-const-reference conversion: T => const T &
175                                        return Cost::safe;
176                                } else {
177                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
178                                        // rvalue-to-reference conversion: T => T &
179                                        return Cost::unsafe;
180                                } // if
181                        } // if
182                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
183                }
184                return Cost::infinity;
185        }
186
187        Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
188                        const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
189                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
190                Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
191                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
192                return cost;
193        }
194
195        ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
196                : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
197        }
198
199        // GENERATED START, DO NOT EDIT
200        // GENERATED BY BasicTypes-gen.cc
201        /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
202                                 _Bool
203        char                signed char         unsigned char
204                  signed short int         unsigned short int
205                  signed int               unsigned int
206                  signed long int          unsigned long int
207                  signed long long int     unsigned long long int
208                  __int128                 unsigned __int128
209                  _Float16                 _Float16 _Complex
210                  _Float32                 _Float32 _Complex
211                  float                    float _Complex
212                  _Float32x                _Float32x _Complex
213                  _Float64                 _Float64 _Complex
214                  double                   double _Complex
215                  _Float64x                _Float64x _Complex
216                             __float80
217                  _Float128                _Float128 _Complex
218                            __float128
219                  long double              long double _Complex
220                  _Float128x               _Float128x _Complex
221        */
222        // GENERATED END
223
224        // GENERATED START, DO NOT EDIT
225        // GENERATED BY BasicTypes-gen.cc
226        static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
227                /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
228                /*      B */ {   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,  17,  16,  18,  17, },
229                /*      C */ {  -1,   0,   1,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
230                /*     SC */ {  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
231                /*     UC */ {  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
232                /*     SI */ {  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
233                /*    SUI */ {  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
234                /*      I */ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
235                /*     UI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
236                /*     LI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
237                /*    LUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
238                /*    LLI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
239                /*   LLUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
240                /*     IB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
241                /*    UIB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
242                /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,  10,   9,  11,  10, },
243                /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,   6,  -1,  -1,   7,  -1,  -1,   8,  -1,   9, },
244                /*     _F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   9,   8,  10,   9, },
245                /*    _FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,  -1,   6,  -1,  -1,   7,  -1,   8, },
246                /*      F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   8,   7,   9,   8, },
247                /*     FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,  -1,   5,  -1,  -1,   6,  -1,   7, },
248                /*    _FX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   6,   8,   7, },
249                /*   _FXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,  -1,   4,  -1,  -1,   5,  -1,   6, },
250                /*     FD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   5,   7,   6, },
251                /*   _FDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,  -1,   3,  -1,  -1,   4,  -1,   5, },
252                /*      D */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   4,   6,   5, },
253                /*     DC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,  -1,   2,  -1,  -1,   3,  -1,   4, },
254                /*   F80X */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   3,   5,   4, },
255                /*  _FDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,  -1,   2,  -1,   3, },
256                /*    F80 */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3,   3,   4,   4, },
257                /*    _FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3, },
258                /*  _FLDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,   2, },
259                /*     FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3, },
260                /*     LD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2, },
261                /*    LDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1, },
262                /*   _FBX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1, },
263                /* _FLDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
264        }; // costMatrix
265        static const int maxIntCost = 15;
266        // GENERATED END
267        static_assert(
268                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
269                "Missing row in the cost matrix"
270        );
271
272        // GENERATED START, DO NOT EDIT
273        // GENERATED BY BasicTypes-gen.cc
274        static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
275                /*               B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
276                /*      B */ {   0,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
277                /*      C */ {  -1,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
278                /*     SC */ {  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
279                /*     UC */ {  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
280                /*     SI */ {  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
281                /*    SUI */ {  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
282                /*      I */ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
283                /*     UI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
284                /*     LI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
285                /*    LUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
286                /*    LLI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
287                /*   LLUI */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
288                /*     IB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
289                /*    UIB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
290                /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
291                /*    _FH */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
292                /*     _F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
293                /*    _FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
294                /*      F */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
295                /*     FC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
296                /*    _FX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
297                /*   _FXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
298                /*     FD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
299                /*   _FDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
300                /*      D */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
301                /*     DC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
302                /*   F80X */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
303                /*  _FDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
304                /*    F80 */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
305                /*    _FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0, },
306                /*  _FLDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
307                /*     FB */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0, },
308                /*     LD */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0, },
309                /*    LDC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0, },
310                /*   _FBX */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0, },
311                /* _FLDXC */ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
312        }; // signMatrix
313        // GENERATED END
314        static_assert(
315                sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
316                "Missing row in the sign matrix"
317        );
318
319        void ConversionCost::postvisit( const VoidType * ) {
320                cost = Cost::infinity;
321        }
322
323        void ConversionCost::postvisit(const BasicType * basicType) {
324                if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
325                        int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
326                        if ( tableResult == -1 ) {
327                                cost = Cost::unsafe;
328                        } else {
329                                cost = Cost::zero;
330                                cost.incSafe( tableResult );
331                                cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
332                        } // if
333                } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
334                        // xxx - not positive this is correct, but appears to allow casting int => enum
335                        cost = Cost::unsafe;
336                } // if
337                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
338        }
339
340        void ConversionCost::postvisit( const PointerType * pointerType ) {
341                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
342                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
343                        Type::Qualifiers tq1 = pointerType->base->tq;
344                        Type::Qualifiers tq2 = destAsPtr->base->tq;
345                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
346                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
347                                if ( tq1 == tq2 ) {
348                                        // types are the same
349                                        cost = Cost::zero;
350                                } else {
351                                        // types are the same, except otherPointer has more qualifiers
352                                        cost = Cost::safe;
353                                } // if
354                        } else {
355                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
356                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
357                                if ( assignResult > 0 && tq1 <= tq2 ) {
358                                        // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
359                                        if ( tq1 == tq2 ) {
360                                                cost = Cost::safe;
361                                        } else if ( tq1 < tq2 ) {
362                                                cost = Cost::safe+Cost::safe;
363                                        }
364                                } else if ( assignResult < 0 ) {
365                                        cost = Cost::unsafe;
366                                } // if
367                                // assignResult == 0 means Cost::Infinity
368                        } // if
369                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
370                } // if
371        }
372
373        void ConversionCost::postvisit( const ArrayType * ) {}
374
375        void ConversionCost::postvisit( const ReferenceType * refType ) {
376                // Note: dest can never be a reference, since it would have been caught in an earlier check
377                assert( ! dynamic_cast< const ReferenceType * >( dest ) );
378                // convert reference to rvalue: cv T1 & => T2
379                // recursively compute conversion cost from T1 to T2.
380                // cv can be safely dropped because of 'implicit dereference' behavior.
381                cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
382                if ( refType->base->tq == dest->tq ) {
383                        cost.incReference();  // prefer exact qualifiers
384                } else if ( refType->base->tq < dest->tq ) {
385                        cost.incSafe(); // then gaining qualifiers
386                } else {
387                        cost.incUnsafe(); // lose qualifiers as last resort
388                }
389                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
390        }
391
392        void ConversionCost::postvisit( const FunctionType * ) {}
393
394        void ConversionCost::postvisit( const EnumInstType * ) {
395                static Type::Qualifiers q;
396                static BasicType integer( q, BasicType::SignedInt );
397                cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
398                if ( cost < Cost::unsafe ) {
399                        cost.incSafe();
400                } // if
401        }
402
403        void ConversionCost::postvisit( const TraitInstType * ) {}
404
405        void ConversionCost::postvisit( const TypeInstType * inst ) {
406                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
407                        cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
408                } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
409                        if ( inst->name == destAsInst->name ) {
410                                cost = Cost::zero;
411                        }
412                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
413                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
414                        // all typedefs should be gone by this point
415                        assert( type );
416                        if ( type->base ) {
417                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
418                        } // if
419                } // if
420        }
421
422        void ConversionCost::postvisit( const TupleType * tupleType ) {
423                Cost c = Cost::zero;
424                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
425                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
426                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
427                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
428                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
429                                if ( newCost == Cost::infinity ) {
430                                        return;
431                                } // if
432                                c += newCost;
433                        } // while
434                        if ( destIt != destAsTuple->types.end() ) {
435                                cost = Cost::infinity;
436                        } else {
437                                cost = c;
438                        } // if
439                } // if
440        }
441
442        void ConversionCost::postvisit( const VarArgsType * ) {
443                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
444                        cost = Cost::zero;
445                }
446        }
447
448        void ConversionCost::postvisit( const ZeroType * ) {
449                if ( dynamic_cast< const ZeroType * >( dest ) ) {
450                        cost = Cost::zero;
451                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
452                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
453                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
454                        if ( tableResult == -1 ) {
455                                cost = Cost::unsafe;
456                        } else {
457                                cost = Cost::zero;
458                                cost.incSafe( tableResult + 1 );
459                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
460                        } // if
461                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
462                        cost = Cost::zero;
463                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
464                } // if
465        }
466
467        void ConversionCost::postvisit( const OneType * ) {
468                if ( dynamic_cast< const OneType * >( dest ) ) {
469                        cost = Cost::zero;
470                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
471                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
472                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
473                        if ( tableResult == -1 ) {
474                                cost = Cost::unsafe;
475                        } else {
476                                cost = Cost::zero;
477                                cost.incSafe( tableResult + 1 );
478                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
479                        } // if
480                } // if
481        }
482
483namespace {
484        # warning For overload resolution between the two versions.
485        int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
486                        const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
487                return ptrsAssignable( t1, t2, env );
488        }
489        Cost localConversionCost(
490                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
491                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
492        ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
493}
494
495Cost conversionCost(
496        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
497        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
498) {
499        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
500                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
501                        if ( eqv->bound ) {
502                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
503                        } else {
504                                return Cost::infinity;
505                        }
506                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
507                        const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
508                        assertf( type, "Unexpected typedef." );
509                        if ( type->base ) {
510                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
511                        }
512                }
513        }
514        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
515                return Cost::zero;
516        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
517                return Cost::safe;
518        } else if ( const ast::ReferenceType * refType =
519                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
520                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
521        } else {
522                ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
523                src->accept( converter );
524                return converter.pass.cost;
525        }
526}
527
528static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
529                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
530                PtrsCalculation func ) {
531        if ( 0 < diff ) {
532                Cost cost = convertToReferenceCost(
533                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
534                        srcIsLvalue, (diff - 1), symtab, env, func );
535                cost.incReference();
536                return cost;
537        } else if ( diff < -1 ) {
538                Cost cost = convertToReferenceCost(
539                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
540                        srcIsLvalue, (diff + 1), symtab, env, func );
541                cost.incReference();
542                return cost;
543        } else if ( 0 == diff ) {
544                const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
545                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
546                if ( srcAsRef && dstAsRef ) {
547                        ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
548                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
549                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
550                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
551                                if ( tq1 == tq2 ) {
552                                        return Cost::zero;
553                                } else {
554                                        return Cost::safe;
555                                }
556                        } else {
557                                int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
558                                if ( 0 < assignResult ) {
559                                        return Cost::safe;
560                                } else if ( assignResult < 0 ) {
561                                        return Cost::unsafe;
562                                }
563                        }
564                } else {
565                        ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
566                        src->accept( converter );
567                        return converter.pass.cost;
568                }
569        } else {
570                assert( -1 == diff );
571                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
572                assert( dstAsRef );
573                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
574                        if ( srcIsLvalue ) {
575                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
576                                        return Cost::reference;
577                                } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
578                                        return Cost::safe;
579                                } else {
580                                        return Cost::unsafe;
581                                }
582                        } else if ( dstAsRef->base->is_const() ) {
583                                return Cost::safe;
584                        } else {
585                                return Cost::unsafe;
586                        }
587                }
588        }
589        return Cost::infinity;
590}
591
592Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
593                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
594                PtrsCalculation func ) {
595        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
596        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
597}
598
599void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
600        (void)voidType;
601        cost = Cost::infinity;
602}
603
604void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
605        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
606                int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
607                if ( tableResult == -1 ) {
608                        cost = Cost::unsafe;
609                } else {
610                        cost = Cost::zero;
611                        cost.incSafe( tableResult );
612                        cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
613                }
614        } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
615                // xxx - not positive this is correct, but appears to allow casting int => enum
616                cost = Cost::unsafe;
617        }
618}
619
620void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
621        if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
622                ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
623                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
624                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
625                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
626                        if ( tq1 == tq2 ) {
627                                cost = Cost::zero;
628                        } else {
629                                cost = Cost::safe;
630                        }
631                } else {
632                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
633                        if ( 0 < assignResult && tq1 <= tq2 ) {
634                                if ( tq1 == tq2 ) {
635                                        cost = Cost::safe;
636                                } else {
637                                        cost = Cost::safe + Cost::safe;
638                                }
639                        } else if ( assignResult < 0 ) {
640                                cost = Cost::unsafe;
641                        } // else Cost::infinity
642                }
643        }
644}
645
646void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
647        (void)arrayType;
648}
649
650void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
651        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
652
653        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
654        if ( refType->base->qualifiers == dst->qualifiers ) {
655                cost.incReference();
656        } else if ( refType->base->qualifiers < dst->qualifiers ) {
657                cost.incSafe();
658        } else {
659                cost.incUnsafe();
660        }
661}
662
663void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
664        (void)functionType;
665}
666
667void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
668        (void)enumInstType;
669        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
670        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
671        if ( cost < Cost::unsafe ) {
672                cost.incSafe();
673        }
674}
675
676void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
677        (void)traitInstType;
678}
679
680void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
681        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
682                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
683        } else if ( const ast::TypeInstType * dstAsInst =
684                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
685                if ( typeInstType->name == dstAsInst->name ) {
686                        cost = Cost::zero;
687                }
688        } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
689                const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
690                assertf( type, "Unexpected typedef.");
691                if ( type->base ) {
692                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
693                }
694        }
695}
696
697void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
698        Cost c = Cost::zero;
699        if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
700                auto srcIt = tupleType->types.begin();
701                auto dstIt = dstAsTuple->types.begin();
702                auto srcEnd = tupleType->types.end();
703                auto dstEnd = dstAsTuple->types.end();
704                while ( srcIt != srcEnd && dstIt != dstEnd ) {
705                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
706                        if ( newCost == Cost::infinity ) {
707                                return;
708                        }
709                        c += newCost;
710                }
711                if ( dstIt != dstEnd ) {
712                        cost = Cost::infinity;
713                } else {
714                        cost = c;
715                }
716        }
717}
718
719void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
720        (void)varArgsType;
721        if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
722                cost = Cost::zero;
723        }
724}
725
726void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
727        (void)zeroType;
728        if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
729                cost = Cost::zero;
730        } else if ( const ast::BasicType * dstAsBasic =
731                        dynamic_cast< const ast::BasicType * >( dst ) ) {
732                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
733                if ( -1 == tableResult ) {
734                        cost = Cost::unsafe;
735                } else {
736                        cost = Cost::zero;
737                        cost.incSafe( tableResult + 1 );
738                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
739                }
740        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
741                cost = Cost::zero;
742                // +1 for zero_t ->, +1 for disambiguation
743                cost.incSafe( maxIntCost + 2 );
744        }
745}
746
747void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
748        (void)oneType;
749        if ( dynamic_cast< const ast::OneType * >( dst ) ) {
750                cost = Cost::zero;
751        } else if ( const ast::BasicType * dstAsBasic =
752                        dynamic_cast< const ast::BasicType * >( dst ) ) {
753                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
754                if ( -1 == tableResult ) {
755                        cost = Cost::unsafe;
756                } else {
757                        cost = Cost::zero;
758                        cost.incSafe( tableResult + 1 );
759                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
760                }
761        }
762}
763// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
764
765} // namespace ResolvExpr
766
767// Local Variables: //
768// tab-width: 4 //
769// mode: c++ //
770// compile-command: "make install" //
771// End: //
Note: See TracBrowser for help on using the repository browser.