source: src/ResolvExpr/ConversionCost.cc @ 6a823241

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since 6a823241 was 3e5dd913, checked in by Fangren Yu <f37yu@…>, 4 years ago

reimplement function type and eliminate deep copy

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