source: src/ResolvExpr/ConversionCost.cc @ 14388c1

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 14388c1 was 7d01cf44, checked in by Andrew Beach <ajbeach@…>, 5 years ago

lvalue is now read through the expression.

  • Property mode set to 100644
File size: 41.6 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 : Mon Aug 12 10:21:00 2019
13// Update Count     : 27
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                                assert( src->get_lvalue() == srcIsLvalue );
160                                if ( srcIsLvalue ) {
161                                        PRINT(
162                                                std::cerr << "lvalue to reference conversion" << std::endl;
163                                                std::cerr << src << " => " << destAsRef << std::endl;
164                                        )
165                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
166                                        if ( src->tq == destAsRef->base->tq ) {
167                                                return Cost::reference; // cost needs to be non-zero to add cast
168                                        } if ( src->tq < destAsRef->base->tq ) {
169                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
170                                        } else {
171                                                return Cost::unsafe;
172                                        } // if
173                                } else if ( destAsRef->base->get_const() ) {
174                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
175                                        // rvalue-to-const-reference conversion: T => const T &
176                                        return Cost::safe;
177                                } else {
178                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
179                                        // rvalue-to-reference conversion: T => T &
180                                        return Cost::unsafe;
181                                } // if
182                        } // if
183                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
184                }
185                return Cost::infinity;
186        }
187
188        Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
189                        const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
190                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
191                Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
192                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
193                return cost;
194        }
195
196        ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
197                : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
198        }
199
200        // GENERATED START, DO NOT EDIT
201        // GENERATED BY BasicTypes-gen.cc
202        /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
203                                 _Bool
204        char                signed char         unsigned char
205                  signed short int         unsigned short int
206                  signed int               unsigned int
207                  signed long int          unsigned long int
208                  signed long long int     unsigned long long int
209                  __int128                 unsigned __int128
210                  _Float16                 _Float16 _Complex
211                  _Float32                 _Float32 _Complex
212                  float                    float _Complex
213                  _Float32x                _Float32x _Complex
214                  _Float64                 _Float64 _Complex
215                  double                   double _Complex
216                  _Float64x                _Float64x _Complex
217                             __float80
218                  _Float128                _Float128 _Complex
219                            __float128
220                  long double              long double _Complex
221                  _Float128x               _Float128x _Complex
222        */
223        // GENERATED END
224
225        // GENERATED START, DO NOT EDIT
226        // GENERATED BY BasicTypes-gen.cc
227        static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
228                /*               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 */
229                /*      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, },
230                /*      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, },
231                /*     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, },
232                /*     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, },
233                /*     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, },
234                /*    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, },
235                /*      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, },
236                /*     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, },
237                /*     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, },
238                /*    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, },
239                /*    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, },
240                /*   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, },
241                /*     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, },
242                /*    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, },
243                /*    _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, },
244                /*    _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, },
245                /*     _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, },
246                /*    _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, },
247                /*      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, },
248                /*     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, },
249                /*    _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, },
250                /*   _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, },
251                /*     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, },
252                /*   _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, },
253                /*      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, },
254                /*     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, },
255                /*   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, },
256                /*  _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, },
257                /*    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, },
258                /*    _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, },
259                /*  _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, },
260                /*     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, },
261                /*     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, },
262                /*    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, },
263                /*   _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, },
264                /* _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, },
265        }; // costMatrix
266        static const int maxIntCost = 15;
267        // GENERATED END
268        static_assert(
269                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
270                "Missing row in the cost matrix"
271        );
272
273        // GENERATED START, DO NOT EDIT
274        // GENERATED BY BasicTypes-gen.cc
275        static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
276                /*               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 */
277                /*      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, },
278                /*      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, },
279                /*     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, },
280                /*     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, },
281                /*     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, },
282                /*    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, },
283                /*      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, },
284                /*     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, },
285                /*     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, },
286                /*    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, },
287                /*    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, },
288                /*   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, },
289                /*     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, },
290                /*    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, },
291                /*    _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, },
292                /*    _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, },
293                /*     _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, },
294                /*    _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, },
295                /*      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, },
296                /*     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, },
297                /*    _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, },
298                /*   _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, },
299                /*     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, },
300                /*   _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, },
301                /*      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, },
302                /*     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, },
303                /*   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, },
304                /*  _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, },
305                /*    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, },
306                /*    _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, },
307                /*  _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, },
308                /*     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, },
309                /*     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, },
310                /*    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, },
311                /*   _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, },
312                /* _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, },
313        }; // signMatrix
314        // GENERATED END
315        static_assert(
316                sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
317                "Missing row in the sign matrix"
318        );
319
320        void ConversionCost::postvisit( const VoidType * ) {
321                cost = Cost::infinity;
322        }
323
324        void ConversionCost::postvisit(const BasicType * basicType) {
325                if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
326                        int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
327                        if ( tableResult == -1 ) {
328                                cost = Cost::unsafe;
329                        } else {
330                                cost = Cost::zero;
331                                cost.incSafe( tableResult );
332                                cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
333                        } // if
334                } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
335                        // xxx - not positive this is correct, but appears to allow casting int => enum
336                        cost = Cost::unsafe;
337                } // if
338                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
339        }
340
341        void ConversionCost::postvisit( const PointerType * pointerType ) {
342                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
343                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
344                        Type::Qualifiers tq1 = pointerType->base->tq;
345                        Type::Qualifiers tq2 = destAsPtr->base->tq;
346                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
347                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
348                                if ( tq1 == tq2 ) {
349                                        // types are the same
350                                        cost = Cost::zero;
351                                } else {
352                                        // types are the same, except otherPointer has more qualifiers
353                                        cost = Cost::safe;
354                                } // if
355                        } else {
356                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
357                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
358                                if ( assignResult > 0 && tq1 <= tq2 ) {
359                                        // 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?
360                                        if ( tq1 == tq2 ) {
361                                                cost = Cost::safe;
362                                        } else if ( tq1 < tq2 ) {
363                                                cost = Cost::safe+Cost::safe;
364                                        }
365                                } else if ( assignResult < 0 ) {
366                                        cost = Cost::unsafe;
367                                } // if
368                                // assignResult == 0 means Cost::Infinity
369                        } // if
370                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
371                } // if
372        }
373
374        void ConversionCost::postvisit( const ArrayType * ) {}
375
376        void ConversionCost::postvisit( const ReferenceType * refType ) {
377                // Note: dest can never be a reference, since it would have been caught in an earlier check
378                assert( ! dynamic_cast< const ReferenceType * >( dest ) );
379                // convert reference to rvalue: cv T1 & => T2
380                // recursively compute conversion cost from T1 to T2.
381                // cv can be safely dropped because of 'implicit dereference' behavior.
382                cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
383                if ( refType->base->tq == dest->tq ) {
384                        cost.incReference();  // prefer exact qualifiers
385                } else if ( refType->base->tq < dest->tq ) {
386                        cost.incSafe(); // then gaining qualifiers
387                } else {
388                        cost.incUnsafe(); // lose qualifiers as last resort
389                }
390                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
391        }
392
393        void ConversionCost::postvisit( const FunctionType * ) {}
394
395        void ConversionCost::postvisit( const StructInstType * inst ) {
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        void ConversionCost::postvisit( const UnionInstType * inst ) {
404                if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
405                        if ( inst->name == destAsInst->name ) {
406                                cost = Cost::zero;
407                        } // if
408                } // if
409        }
410
411        void ConversionCost::postvisit( const EnumInstType * ) {
412                static Type::Qualifiers q;
413                static BasicType integer( q, BasicType::SignedInt );
414                cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
415                if ( cost < Cost::unsafe ) {
416                        cost.incSafe();
417                } // if
418        }
419
420        void ConversionCost::postvisit( const TraitInstType * ) {}
421
422        void ConversionCost::postvisit( const TypeInstType * inst ) {
423                if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
424                        cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
425                } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
426                        if ( inst->name == destAsInst->name ) {
427                                cost = Cost::zero;
428                        }
429                } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
430                        const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
431                        // all typedefs should be gone by this point
432                        assert( type );
433                        if ( type->base ) {
434                                cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
435                        } // if
436                } // if
437        }
438
439        void ConversionCost::postvisit( const TupleType * tupleType ) {
440                Cost c = Cost::zero;
441                if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
442                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
443                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
444                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
445                                Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
446                                if ( newCost == Cost::infinity ) {
447                                        return;
448                                } // if
449                                c += newCost;
450                        } // while
451                        if ( destIt != destAsTuple->types.end() ) {
452                                cost = Cost::infinity;
453                        } else {
454                                cost = c;
455                        } // if
456                } // if
457        }
458
459        void ConversionCost::postvisit( const VarArgsType * ) {
460                if ( dynamic_cast< const VarArgsType * >( dest ) ) {
461                        cost = Cost::zero;
462                }
463        }
464
465        void ConversionCost::postvisit( const ZeroType * ) {
466                if ( dynamic_cast< const ZeroType * >( dest ) ) {
467                        cost = Cost::zero;
468                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
469                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
470                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
471                        if ( tableResult == -1 ) {
472                                cost = Cost::unsafe;
473                        } else {
474                                cost = Cost::zero;
475                                cost.incSafe( tableResult + 1 );
476                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
477                        } // if
478                } else if ( dynamic_cast< const PointerType * >( dest ) ) {
479                        cost = Cost::zero;
480                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
481                } // if
482        }
483
484        void ConversionCost::postvisit( const OneType * ) {
485                if ( dynamic_cast< const OneType * >( dest ) ) {
486                        cost = Cost::zero;
487                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
488                        // copied from visit(BasicType *) for signed int, but +1 for safe conversions
489                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
490                        if ( tableResult == -1 ) {
491                                cost = Cost::unsafe;
492                        } else {
493                                cost = Cost::zero;
494                                cost.incSafe( tableResult + 1 );
495                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
496                        } // if
497                } // if
498        }
499
500static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
501                const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
502        return ptrsAssignable( t1, t2, env );
503}
504
505// TODO: This is used for overload resolution. It might be able to be dropped once the old system
506// is removed.
507static Cost localConversionCost(
508        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
509        const ast::TypeEnvironment & env
510) { return conversionCost( src, dst, symtab, env ); }
511
512Cost conversionCost(
513        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
514        const ast::TypeEnvironment & env
515) {
516        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
517                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
518                        if ( eqv->bound ) {
519                                return conversionCost(src, eqv->bound, symtab, env );
520                        } else {
521                                return Cost::infinity;
522                        }
523                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
524                        const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
525                        assertf( type, "Unexpected typedef." );
526                        if ( type->base ) {
527                                return conversionCost( src, type->base, symtab, env ) + Cost::safe;
528                        }
529                }
530        }
531        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
532                return Cost::zero;
533        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
534                return Cost::safe;
535        } else if ( const ast::ReferenceType * refType =
536                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
537                return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
538        } else {
539                ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
540                src->accept( converter );
541                return converter.pass.cost;
542        }
543}
544
545static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
546                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
547                NumCostCalculation func ) {
548        if ( 0 < diff ) {
549                Cost cost = convertToReferenceCost(
550                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
551                        dst, (diff - 1), symtab, env, func );
552                cost.incReference();
553                return cost;
554        } else if ( diff < -1 ) {
555                Cost cost = convertToReferenceCost(
556                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
557                        (diff + 1), symtab, env, func );
558                cost.incReference();
559                return cost;
560        } else if ( 0 == diff ) {
561                const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
562                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
563                if ( srcAsRef && dstAsRef ) {
564                        ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
565                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
566                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
567                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
568                                if ( tq1 == tq2 ) {
569                                        return Cost::zero;
570                                } else {
571                                        return Cost::safe;
572                                }
573                        } else {
574                                int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
575                                if ( 0 < assignResult ) {
576                                        return Cost::safe;
577                                } else if ( assignResult < 0 ) {
578                                        return Cost::unsafe;
579                                }
580                        }
581                } else {
582                        ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
583                        src->accept( converter );
584                        return converter.pass.cost;
585                }
586        } else {
587                assert( -1 == diff );
588                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
589                assert( dstAsRef );
590                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
591                        if ( src->is_lvalue() ) {
592                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
593                                        return Cost::reference;
594                                } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
595                                        return Cost::safe;
596                                } else {
597                                        return Cost::unsafe;
598                                }
599                        } else if ( dstAsRef->base->is_const() ) {
600                                return Cost::safe;
601                        } else {
602                                return Cost::unsafe;
603                        }
604                }
605        }
606        return Cost::infinity;
607}
608
609Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
610            const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
611                NumCostCalculation func ) {
612        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
613        return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
614}
615
616void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
617        (void)voidType;
618        cost = Cost::infinity;
619}
620
621void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
622        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
623                int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
624                if ( tableResult == -1 ) {
625                        cost = Cost::unsafe;
626                } else {
627                        cost = Cost::zero;
628                        cost.incSafe( tableResult );
629                        cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
630                }
631        } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
632                // xxx - not positive this is correct, but appears to allow casting int => enum
633                cost = Cost::unsafe;
634        }
635}
636
637void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
638        if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
639                ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
640                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
641                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
642                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
643                        if ( tq1 == tq2 ) {
644                                cost = Cost::zero;
645                        } else {
646                                cost = Cost::safe;
647                        }
648                } else {
649                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
650                        if ( 0 < assignResult && tq1 <= tq2 ) {
651                                if ( tq1 == tq2 ) {
652                                        cost = Cost::safe;
653                                } else {
654                                        cost = Cost::safe + Cost::safe;
655                                }
656                        } else if ( assignResult < 0 ) {
657                                cost = Cost::unsafe;
658                        } // else Cost::infinity
659                }
660        }
661}
662
663void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
664        (void)arrayType;
665}
666
667void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
668        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
669
670        cost = costCalc( refType->base, dst, symtab, env );
671        if ( refType->base->qualifiers == dst->qualifiers ) {
672                cost.incReference();
673        } else if ( refType->base->qualifiers < dst->qualifiers ) {
674                cost.incSafe();
675        } else {
676                cost.incUnsafe();
677        }
678}
679
680void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
681        (void)functionType;
682}
683
684void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
685        if ( const ast::StructInstType * dstAsInst =
686                        dynamic_cast< const ast::StructInstType * >( dst ) ) {
687                if ( structInstType->name == dstAsInst->name ) {
688                        cost = Cost::zero;
689                }
690        }
691}
692
693void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
694        if ( const ast::UnionInstType * dstAsInst =
695                        dynamic_cast< const ast::UnionInstType * >( dst ) ) {
696                if ( unionInstType->name == dstAsInst->name ) {
697                        cost = Cost::zero;
698                }
699        }
700}
701
702void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
703        (void)enumInstType;
704        static const ast::BasicType integer( ast::BasicType::SignedInt );
705        cost = costCalc( &integer, dst, symtab, env );
706        if ( cost < Cost::unsafe ) {
707                cost.incSafe();
708        }
709}
710
711void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
712        (void)traitInstType;
713}
714
715void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
716        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
717                cost = costCalc( eqv->bound, dst, symtab, env );
718        } else if ( const ast::TypeInstType * dstAsInst =
719                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
720                if ( typeInstType->name == dstAsInst->name ) {
721                        cost = Cost::zero;
722                }
723        } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
724                const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
725                assertf( type, "Unexpected typedef.");
726                if ( type->base ) {
727                        cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
728                }
729        }
730}
731
732void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
733        Cost c = Cost::zero;
734        if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
735                auto srcIt = tupleType->types.begin();
736                auto dstIt = dstAsTuple->types.begin();
737                auto srcEnd = tupleType->types.end();
738                auto dstEnd = dstAsTuple->types.end();
739                while ( srcIt != srcEnd && dstIt != dstEnd ) {
740                        Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
741                        if ( newCost == Cost::infinity ) {
742                                return;
743                        }
744                        c += newCost;
745                }
746                if ( dstIt != dstEnd ) {
747                        cost = Cost::infinity;
748                } else {
749                        cost = c;
750                }
751        }
752}
753
754void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
755        (void)varArgsType;
756        if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
757                cost = Cost::zero;
758        }
759}
760
761void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
762        (void)zeroType;
763        if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
764                cost = Cost::zero;
765        } else if ( const ast::BasicType * dstAsBasic =
766                        dynamic_cast< const ast::BasicType * >( dst ) ) {
767                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
768                if ( -1 == tableResult ) {
769                        cost = Cost::unsafe;
770                } else {
771                        cost = Cost::zero;
772                        cost.incSafe( tableResult + 1 );
773                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
774                }
775        }
776}
777
778void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
779        (void)oneType;
780        if ( dynamic_cast< const ast::OneType * >( dst ) ) {
781                cost = Cost::zero;
782        } else if ( const ast::BasicType * dstAsBasic =
783                        dynamic_cast< const ast::BasicType * >( dst ) ) {
784                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
785                if ( -1 == tableResult ) {
786                        cost = Cost::unsafe;
787                } else {
788                        cost = Cost::zero;
789                        cost.incSafe( tableResult + 1 );
790                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
791                }
792        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
793                cost = Cost::zero;
794                cost.incSafe( maxIntCost + 2 );
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.