source: src/ResolvExpr/ConversionCost.cc @ f403c46

ADTast-experimentalpthread-emulation
Last change on this file since f403c46 was fc134a48, checked in by JiadaL <j82liang@…>, 2 years ago

Implement the struct enum

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