source: src/ResolvExpr/ConversionCost.cc @ cf32116

arm-ehjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since cf32116 was cf32116, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Implemented expression based lvalue resolution on new ast.

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