source: src/ResolvExpr/ConversionCost.cc @ 1f4fde5

ADTast-experimentalpthread-emulationqualifiedEnum
Last change on this file since 1f4fde5 was f238fcc2, checked in by JiadaL <j82liang@…>, 3 years ago

Enable numeric type for typed enum

  • Property mode set to 100644
File size: 41.1 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                        // TODO
336                        EnumDecl * decl = dynamic_cast< const EnumInstType * >( dest )->baseEnum;
337                        if ( decl->base ) {
338                                cost = Cost::infinity;
339                        } else {
340                                cost = Cost::unsafe;
341                        } // if
342                } // if
343                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
344        }
345
346        void ConversionCost::postvisit( const PointerType * pointerType ) {
347                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
348                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
349                        Type::Qualifiers tq1 = pointerType->base->tq;
350                        Type::Qualifiers tq2 = destAsPtr->base->tq;
351                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
352                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
353                                if ( tq1 == tq2 ) {
354                                        // types are the same
355                                        cost = Cost::zero;
356                                } else {
357                                        // types are the same, except otherPointer has more qualifiers
358                                        cost = Cost::safe;
359                                } // if
360                        } else {
361                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
362                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
363                                if ( assignResult > 0 && tq1 <= tq2 ) {
364                                        // 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?
365                                        if ( tq1 == tq2 ) {
366                                                cost = Cost::safe;
367                                        } else if ( tq1 < tq2 ) {
368                                                cost = Cost::safe+Cost::safe;
369                                        }
370                                } else if ( assignResult < 0 ) {
371                                        cost = Cost::unsafe;
372                                } // if
373                                // assignResult == 0 means Cost::Infinity
374                        } // if
375                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
376                } // if
377        }
378
379        void ConversionCost::postvisit( const ArrayType * ) {}
380
381        void ConversionCost::postvisit( const ReferenceType * refType ) {
382                // Note: dest can never be a reference, since it would have been caught in an earlier check
383                assert( ! dynamic_cast< const ReferenceType * >( dest ) );
384                // convert reference to rvalue: cv T1 & => T2
385                // recursively compute conversion cost from T1 to T2.
386                // cv can be safely dropped because of 'implicit dereference' behavior.
387                cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
388                if ( refType->base->tq == dest->tq ) {
389                        cost.incReference();  // prefer exact qualifiers
390                } else if ( refType->base->tq < dest->tq ) {
391                        cost.incSafe(); // then gaining qualifiers
392                } else {
393                        cost.incUnsafe(); // lose qualifiers as last resort
394                }
395                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
396        }
397
398        void ConversionCost::postvisit( const FunctionType * ) {}
399
400        void ConversionCost::postvisit( const EnumInstType * ) {
401                static Type::Qualifiers q;
402                static BasicType integer( q, BasicType::SignedInt );
403                cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
404                if ( cost < Cost::unsafe ) {
405                        cost.incSafe();
406                } // if
407        }
408
409        void ConversionCost::postvisit( const TraitInstType * ) {}
410
411        void ConversionCost::postvisit( const TypeInstType * inst ) {
412                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
413                        cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
414                } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
415                        if ( inst->name == destAsInst->name ) {
416                                cost = Cost::zero;
417                        }
418                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
419                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
420                        // all typedefs should be gone by this point
421                        assert( type );
422                        if ( type->base ) {
423                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
424                        } // if
425                } // if
426        }
427
428        void ConversionCost::postvisit( const TupleType * tupleType ) {
429                Cost c = Cost::zero;
430                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
431                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
432                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
433                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
434                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
435                                if ( newCost == Cost::infinity ) {
436                                        return;
437                                } // if
438                                c += newCost;
439                        } // while
440                        if ( destIt != destAsTuple->types.end() ) {
441                                cost = Cost::infinity;
442                        } else {
443                                cost = c;
444                        } // if
445                } // if
446        }
447
448        void ConversionCost::postvisit( const VarArgsType * ) {
449                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
450                        cost = Cost::zero;
451                }
452        }
453
454        void ConversionCost::postvisit( const ZeroType * ) {
455                if ( dynamic_cast< const ZeroType * >( dest ) ) {
456                        cost = Cost::zero;
457                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
458                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
459                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
460                        if ( tableResult == -1 ) {
461                                cost = Cost::unsafe;
462                        } else {
463                                cost = Cost::zero;
464                                cost.incSafe( tableResult + 1 );
465                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
466                        } // if
467                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
468                        cost = Cost::zero;
469                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
470                } // if
471        }
472
473        void ConversionCost::postvisit( const OneType * ) {
474                if ( dynamic_cast< const OneType * >( dest ) ) {
475                        cost = Cost::zero;
476                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
477                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
478                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
479                        if ( tableResult == -1 ) {
480                                cost = Cost::unsafe;
481                        } else {
482                                cost = Cost::zero;
483                                cost.incSafe( tableResult + 1 );
484                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
485                        } // if
486                } // if
487        }
488
489namespace {
490        # warning For overload resolution between the two versions.
491        int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
492                        const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
493                return ptrsAssignable( t1, t2, env );
494        }
495        Cost localConversionCost(
496                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
497                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
498        ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
499}
500
501Cost conversionCost(
502        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
503        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
504) {
505        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
506                if ( const ast::EqvClass * eqv = env.lookup( *inst ) ) {
507                        if ( eqv->bound ) {
508                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
509                        } else {
510                                return Cost::infinity;
511                        }
512                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
513                        const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
514                        assertf( type, "Unexpected typedef." );
515                        if ( type->base ) {
516                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
517                        }
518                }
519        }
520        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
521                return Cost::zero;
522        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
523                return Cost::safe;
524        } else if ( const ast::ReferenceType * refType =
525                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
526                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
527        } else {
528                return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
529        }
530}
531
532static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
533                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
534                PtrsCalculation func ) {
535        if ( 0 < diff ) {
536                Cost cost = convertToReferenceCost(
537                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
538                        srcIsLvalue, (diff - 1), symtab, env, func );
539                cost.incReference();
540                return cost;
541        } else if ( diff < -1 ) {
542                Cost cost = convertToReferenceCost(
543                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
544                        srcIsLvalue, (diff + 1), symtab, env, func );
545                cost.incReference();
546                return cost;
547        } else if ( 0 == diff ) {
548                const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
549                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
550                if ( srcAsRef && dstAsRef ) {
551                        ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
552                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
553                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
554                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
555                                if ( tq1 == tq2 ) {
556                                        return Cost::zero;
557                                } else {
558                                        return Cost::safe;
559                                }
560                        } else {
561                                int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
562                                if ( 0 < assignResult ) {
563                                        return Cost::safe;
564                                } else if ( assignResult < 0 ) {
565                                        return Cost::unsafe;
566                                }
567                        }
568                } else {
569                        return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
570                }
571        } else {
572                assert( -1 == diff );
573                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
574                assert( dstAsRef );
575                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
576                        if ( srcIsLvalue ) {
577                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
578                                        return Cost::reference;
579                                } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
580                                        return Cost::safe;
581                                } else {
582                                        return Cost::unsafe;
583                                }
584                        } else if ( dstAsRef->base->is_const() ) {
585                                return Cost::safe;
586                        } else {
587                                return Cost::unsafe;
588                        }
589                }
590        }
591        return Cost::infinity;
592}
593
594Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
595                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
596                PtrsCalculation func ) {
597        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
598        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
599}
600
601void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
602        (void)voidType;
603        cost = Cost::infinity;
604}
605
606void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
607        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
608                int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
609                if ( tableResult == -1 ) {
610                        cost = Cost::unsafe;
611                } else {
612                        cost = Cost::zero;
613                        cost.incSafe( tableResult );
614                        cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
615                }
616        } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
617                // xxx - not positive this is correct, but appears to allow casting int => enum
618                const ast::EnumDecl * decl = (dynamic_cast< const ast::EnumInstType * >( dst ))->base.get();
619                if ( decl->base ) {
620                        cost = Cost::infinity;
621                } else {
622                        cost = Cost::unsafe;
623                } // if
624        }
625}
626
627void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
628        if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
629                ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
630                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
631                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
632                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
633                        if ( tq1 == tq2 ) {
634                                cost = Cost::zero;
635                        } else {
636                                cost = Cost::safe;
637                        }
638                } else {
639                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
640                        if ( 0 < assignResult && tq1 <= tq2 ) {
641                                if ( tq1 == tq2 ) {
642                                        cost = Cost::safe;
643                                } else {
644                                        cost = Cost::safe + Cost::safe;
645                                }
646                        } else if ( assignResult < 0 ) {
647                                cost = Cost::unsafe;
648                        } // else Cost::infinity
649                }
650        }
651}
652
653void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
654        (void)arrayType;
655}
656
657void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
658        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
659
660        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
661        if ( refType->base->qualifiers == dst->qualifiers ) {
662                cost.incReference();
663        } else if ( refType->base->qualifiers < dst->qualifiers ) {
664                cost.incSafe();
665        } else {
666                cost.incUnsafe();
667        }
668}
669
670void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
671        (void)functionType;
672}
673
674void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
675        (void)enumInstType;
676        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
677        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
678        if ( cost < Cost::unsafe ) {
679                cost.incSafe();
680        }
681}
682
683void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
684        (void)traitInstType;
685}
686
687void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
688        if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) {
689                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
690        } else if ( const ast::TypeInstType * dstAsInst =
691                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
692                if ( *typeInstType == *dstAsInst ) {
693                        cost = Cost::zero;
694                }
695        } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
696                const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
697                assertf( type, "Unexpected typedef.");
698                if ( type->base ) {
699                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
700                }
701        }
702}
703
704void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
705        Cost c = Cost::zero;
706        if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
707                auto srcIt = tupleType->types.begin();
708                auto dstIt = dstAsTuple->types.begin();
709                auto srcEnd = tupleType->types.end();
710                auto dstEnd = dstAsTuple->types.end();
711                while ( srcIt != srcEnd && dstIt != dstEnd ) {
712                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
713                        if ( newCost == Cost::infinity ) {
714                                return;
715                        }
716                        c += newCost;
717                }
718                if ( dstIt != dstEnd ) {
719                        cost = Cost::infinity;
720                } else {
721                        cost = c;
722                }
723        }
724}
725
726void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
727        (void)varArgsType;
728        if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
729                cost = Cost::zero;
730        }
731}
732
733void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
734        (void)zeroType;
735        if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
736                cost = Cost::zero;
737        } else if ( const ast::BasicType * dstAsBasic =
738                        dynamic_cast< const ast::BasicType * >( dst ) ) {
739                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
740                if ( -1 == tableResult ) {
741                        cost = Cost::unsafe;
742                } else {
743                        cost = Cost::zero;
744                        cost.incSafe( tableResult + 1 );
745                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
746                }
747        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
748                cost = Cost::zero;
749                // +1 for zero_t ->, +1 for disambiguation
750                cost.incSafe( maxIntCost + 2 );
751        }
752}
753
754void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
755        (void)oneType;
756        if ( dynamic_cast< const ast::OneType * >( dst ) ) {
757                cost = Cost::zero;
758        } else if ( const ast::BasicType * dstAsBasic =
759                        dynamic_cast< const ast::BasicType * >( dst ) ) {
760                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
761                if ( -1 == tableResult ) {
762                        cost = Cost::unsafe;
763                } else {
764                        cost = Cost::zero;
765                        cost.incSafe( tableResult + 1 );
766                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
767                }
768        }
769}
770// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
771
772} // namespace ResolvExpr
773
774// Local Variables: //
775// tab-width: 4 //
776// mode: c++ //
777// compile-command: "make install" //
778// End: //
Note: See TracBrowser for help on using the repository browser.