source: src/ResolvExpr/ConversionCost.cc @ e85a72b8

Last change on this file since e85a72b8 was 24d6572, checked in by Fangren Yu <f37yu@…>, 17 months ago

Merge branch 'master' into ast-experimental

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