source: src/ResolvExpr/ConversionCost.cc @ 7870799

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 7870799 was 7870799, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Cast cost and conversion cost now take constant parameters.
This required supporting visiting const node.
The PassVisitor? can now visit const nodes but not when using the Indexer

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