source: src/ResolvExpr/ConversionCost.cc @ eb1be63

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since eb1be63 was eb1be63, checked in by Fangren Yu <f37yu@…>, 4 years ago

conversion cost pass should not consider structs again after types compatible check

  • Property mode set to 100644
File size: 42.0 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 : Fri Oct  4 14:45:00 2019
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 StructInstType * inst ) {
395                /*
396                if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
397                        if ( inst->name == destAsInst->name ) {
398                                cost = Cost::zero;
399                        } // if
400                } // if
401                */
402        }
403
404        void ConversionCost::postvisit( const UnionInstType * inst ) {
405                /*
406                if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
407                        if ( inst->name == destAsInst->name ) {
408                                cost = Cost::zero;
409                        } // if
410                } // if
411                */
412        }
413
414        void ConversionCost::postvisit( const EnumInstType * ) {
415                static Type::Qualifiers q;
416                static BasicType integer( q, BasicType::SignedInt );
417                cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
418                if ( cost < Cost::unsafe ) {
419                        cost.incSafe();
420                } // if
421        }
422
423        void ConversionCost::postvisit( const TraitInstType * ) {}
424
425        void ConversionCost::postvisit( const TypeInstType * inst ) {
426                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
427                        cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
428                } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
429                        if ( inst->name == destAsInst->name ) {
430                                cost = Cost::zero;
431                        }
432                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
433                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
434                        // all typedefs should be gone by this point
435                        assert( type );
436                        if ( type->base ) {
437                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
438                        } // if
439                } // if
440        }
441
442        void ConversionCost::postvisit( const TupleType * tupleType ) {
443                Cost c = Cost::zero;
444                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
445                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
446                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
447                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
448                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
449                                if ( newCost == Cost::infinity ) {
450                                        return;
451                                } // if
452                                c += newCost;
453                        } // while
454                        if ( destIt != destAsTuple->types.end() ) {
455                                cost = Cost::infinity;
456                        } else {
457                                cost = c;
458                        } // if
459                } // if
460        }
461
462        void ConversionCost::postvisit( const VarArgsType * ) {
463                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
464                        cost = Cost::zero;
465                }
466        }
467
468        void ConversionCost::postvisit( const ZeroType * ) {
469                if ( dynamic_cast< const ZeroType * >( dest ) ) {
470                        cost = Cost::zero;
471                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
472                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
473                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
474                        if ( tableResult == -1 ) {
475                                cost = Cost::unsafe;
476                        } else {
477                                cost = Cost::zero;
478                                cost.incSafe( tableResult + 1 );
479                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
480                        } // if
481                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
482                        cost = Cost::zero;
483                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
484                } // if
485        }
486
487        void ConversionCost::postvisit( const OneType * ) {
488                if ( dynamic_cast< const OneType * >( dest ) ) {
489                        cost = Cost::zero;
490                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
491                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
492                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
493                        if ( tableResult == -1 ) {
494                                cost = Cost::unsafe;
495                        } else {
496                                cost = Cost::zero;
497                                cost.incSafe( tableResult + 1 );
498                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
499                        } // if
500                } // if
501        }
502
503namespace {
504        # warning For overload resolution between the two versions.
505        int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
506                        const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
507                return ptrsAssignable( t1, t2, env );
508        }
509        Cost localConversionCost(
510                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
511                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
512        ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
513}
514
515Cost conversionCost(
516        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
517        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
518) {
519        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
520                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
521                        if ( eqv->bound ) {
522                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
523                        } else {
524                                return Cost::infinity;
525                        }
526                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
527                        const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
528                        assertf( type, "Unexpected typedef." );
529                        if ( type->base ) {
530                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
531                        }
532                }
533        }
534        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
535                return Cost::zero;
536        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
537                return Cost::safe;
538        } else if ( const ast::ReferenceType * refType =
539                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
540                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
541        } else {
542                ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
543                src->accept( converter );
544                return converter.pass.cost;
545        }
546}
547
548static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
549                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
550                PtrsCalculation func ) {
551        if ( 0 < diff ) {
552                Cost cost = convertToReferenceCost(
553                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
554                        srcIsLvalue, (diff - 1), symtab, env, func );
555                cost.incReference();
556                return cost;
557        } else if ( diff < -1 ) {
558                Cost cost = convertToReferenceCost(
559                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
560                        srcIsLvalue, (diff + 1), symtab, env, func );
561                cost.incReference();
562                return cost;
563        } else if ( 0 == diff ) {
564                const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
565                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
566                if ( srcAsRef && dstAsRef ) {
567                        ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
568                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
569                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
570                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
571                                if ( tq1 == tq2 ) {
572                                        return Cost::zero;
573                                } else {
574                                        return Cost::safe;
575                                }
576                        } else {
577                                int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
578                                if ( 0 < assignResult ) {
579                                        return Cost::safe;
580                                } else if ( assignResult < 0 ) {
581                                        return Cost::unsafe;
582                                }
583                        }
584                } else {
585                        ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
586                        src->accept( converter );
587                        return converter.pass.cost;
588                }
589        } else {
590                assert( -1 == diff );
591                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
592                assert( dstAsRef );
593                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
594                        if ( srcIsLvalue ) {
595                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
596                                        return Cost::reference;
597                                } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
598                                        return Cost::safe;
599                                } else {
600                                        return Cost::unsafe;
601                                }
602                        } else if ( dstAsRef->base->is_const() ) {
603                                return Cost::safe;
604                        } else {
605                                return Cost::unsafe;
606                        }
607                }
608        }
609        return Cost::infinity;
610}
611
612Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
613                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
614                PtrsCalculation func ) {
615        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
616        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
617}
618
619void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
620        (void)voidType;
621        cost = Cost::infinity;
622}
623
624void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
625        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
626                int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
627                if ( tableResult == -1 ) {
628                        cost = Cost::unsafe;
629                } else {
630                        cost = Cost::zero;
631                        cost.incSafe( tableResult );
632                        cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
633                }
634        } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
635                // xxx - not positive this is correct, but appears to allow casting int => enum
636                cost = Cost::unsafe;
637        }
638}
639
640void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
641        if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
642                ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
643                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
644                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
645                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
646                        if ( tq1 == tq2 ) {
647                                cost = Cost::zero;
648                        } else {
649                                cost = Cost::safe;
650                        }
651                } else {
652                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
653                        if ( 0 < assignResult && tq1 <= tq2 ) {
654                                if ( tq1 == tq2 ) {
655                                        cost = Cost::safe;
656                                } else {
657                                        cost = Cost::safe + Cost::safe;
658                                }
659                        } else if ( assignResult < 0 ) {
660                                cost = Cost::unsafe;
661                        } // else Cost::infinity
662                }
663        }
664}
665
666void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
667        (void)arrayType;
668}
669
670void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
671        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
672
673        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
674        if ( refType->base->qualifiers == dst->qualifiers ) {
675                cost.incReference();
676        } else if ( refType->base->qualifiers < dst->qualifiers ) {
677                cost.incSafe();
678        } else {
679                cost.incUnsafe();
680        }
681}
682
683void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
684        (void)functionType;
685}
686
687void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
688        /*
689        if ( const ast::StructInstType * dstAsInst =
690                        dynamic_cast< const ast::StructInstType * >( dst ) ) {
691                if ( structInstType->name == dstAsInst->name ) {
692                        cost = Cost::zero;
693                }
694        }
695        */
696}
697
698void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
699        /*
700        if ( const ast::UnionInstType * dstAsInst =
701                        dynamic_cast< const ast::UnionInstType * >( dst ) ) {
702                if ( unionInstType->name == dstAsInst->name ) {
703                        cost = Cost::zero;
704                }
705        }
706        */
707}
708
709void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
710        (void)enumInstType;
711        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
712        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
713        if ( cost < Cost::unsafe ) {
714                cost.incSafe();
715        }
716}
717
718void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
719        (void)traitInstType;
720}
721
722void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
723        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
724                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
725        } else if ( const ast::TypeInstType * dstAsInst =
726                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
727                if ( typeInstType->name == dstAsInst->name ) {
728                        cost = Cost::zero;
729                }
730        } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
731                const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
732                assertf( type, "Unexpected typedef.");
733                if ( type->base ) {
734                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
735                }
736        }
737}
738
739void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
740        Cost c = Cost::zero;
741        if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
742                auto srcIt = tupleType->types.begin();
743                auto dstIt = dstAsTuple->types.begin();
744                auto srcEnd = tupleType->types.end();
745                auto dstEnd = dstAsTuple->types.end();
746                while ( srcIt != srcEnd && dstIt != dstEnd ) {
747                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
748                        if ( newCost == Cost::infinity ) {
749                                return;
750                        }
751                        c += newCost;
752                }
753                if ( dstIt != dstEnd ) {
754                        cost = Cost::infinity;
755                } else {
756                        cost = c;
757                }
758        }
759}
760
761void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
762        (void)varArgsType;
763        if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
764                cost = Cost::zero;
765        }
766}
767
768void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
769        (void)zeroType;
770        if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
771                cost = Cost::zero;
772        } else if ( const ast::BasicType * dstAsBasic =
773                        dynamic_cast< const ast::BasicType * >( dst ) ) {
774                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
775                if ( -1 == tableResult ) {
776                        cost = Cost::unsafe;
777                } else {
778                        cost = Cost::zero;
779                        cost.incSafe( tableResult + 1 );
780                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
781                }
782        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
783                cost = Cost::zero;
784                // +1 for zero_t ->, +1 for disambiguation
785                cost.incSafe( maxIntCost + 2 );
786        }
787}
788
789void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
790        (void)oneType;
791        if ( dynamic_cast< const ast::OneType * >( dst ) ) {
792                cost = Cost::zero;
793        } else if ( const ast::BasicType * dstAsBasic =
794                        dynamic_cast< const ast::BasicType * >( dst ) ) {
795                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
796                if ( -1 == tableResult ) {
797                        cost = Cost::unsafe;
798                } else {
799                        cost = Cost::zero;
800                        cost.incSafe( tableResult + 1 );
801                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
802                }
803        }
804}
805size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
806
807} // namespace ResolvExpr
808
809// Local Variables: //
810// tab-width: 4 //
811// mode: c++ //
812// compile-command: "make install" //
813// End: //
Note: See TracBrowser for help on using the repository browser.