source: src/ResolvExpr/ConversionCost.cc @ 4520b77e

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

Fix up the QualifiedNameExpr?. It should now work on both old AST and new AST. There are some known bugs to fix so make all-tests will fail.

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