source: src/ResolvExpr/ConversionCost.cc@ 2e9b59b

ADT ast-experimental pthread-emulation qualifiedEnum
Last change on this file since 2e9b59b was f238fcc2, checked in by JiadaL <j82liang@…>, 4 years ago

Enable numeric type for typed enum

  • Property mode set to 100644
File size: 41.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ConversionCost.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 07:06:19 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : 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 // TODO
336 EnumDecl * decl = dynamic_cast< const EnumInstType * >( dest )->baseEnum;
337 if ( decl->base ) {
338 cost = Cost::infinity;
339 } else {
340 cost = Cost::unsafe;
341 } // if
342 } // if
343 // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
344 }
345
346 void ConversionCost::postvisit( const PointerType * pointerType ) {
347 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
348 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
349 Type::Qualifiers tq1 = pointerType->base->tq;
350 Type::Qualifiers tq2 = destAsPtr->base->tq;
351 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
352 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
353 if ( tq1 == tq2 ) {
354 // types are the same
355 cost = Cost::zero;
356 } else {
357 // types are the same, except otherPointer has more qualifiers
358 cost = Cost::safe;
359 } // if
360 } else {
361 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
362 PRINT( std::cerr << " :: " << assignResult << std::endl; )
363 if ( assignResult > 0 && tq1 <= tq2 ) {
364 // 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?
365 if ( tq1 == tq2 ) {
366 cost = Cost::safe;
367 } else if ( tq1 < tq2 ) {
368 cost = Cost::safe+Cost::safe;
369 }
370 } else if ( assignResult < 0 ) {
371 cost = Cost::unsafe;
372 } // if
373 // assignResult == 0 means Cost::Infinity
374 } // if
375 // case case for zero_t because it should not be possible to convert pointers to zero_t.
376 } // if
377 }
378
379 void ConversionCost::postvisit( const ArrayType * ) {}
380
381 void ConversionCost::postvisit( const ReferenceType * refType ) {
382 // Note: dest can never be a reference, since it would have been caught in an earlier check
383 assert( ! dynamic_cast< const ReferenceType * >( dest ) );
384 // convert reference to rvalue: cv T1 & => T2
385 // recursively compute conversion cost from T1 to T2.
386 // cv can be safely dropped because of 'implicit dereference' behavior.
387 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
388 if ( refType->base->tq == dest->tq ) {
389 cost.incReference(); // prefer exact qualifiers
390 } else if ( refType->base->tq < dest->tq ) {
391 cost.incSafe(); // then gaining qualifiers
392 } else {
393 cost.incUnsafe(); // lose qualifiers as last resort
394 }
395 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
396 }
397
398 void ConversionCost::postvisit( const FunctionType * ) {}
399
400 void ConversionCost::postvisit( const EnumInstType * ) {
401 static Type::Qualifiers q;
402 static BasicType integer( q, BasicType::SignedInt );
403 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env ); // safe if dest >= int
404 if ( cost < Cost::unsafe ) {
405 cost.incSafe();
406 } // if
407 }
408
409 void ConversionCost::postvisit( const TraitInstType * ) {}
410
411 void ConversionCost::postvisit( const TypeInstType * inst ) {
412 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
413 cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
414 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
415 if ( inst->name == destAsInst->name ) {
416 cost = Cost::zero;
417 }
418 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
419 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
420 // all typedefs should be gone by this point
421 assert( type );
422 if ( type->base ) {
423 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
424 } // if
425 } // if
426 }
427
428 void ConversionCost::postvisit( const TupleType * tupleType ) {
429 Cost c = Cost::zero;
430 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
431 std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
432 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
433 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
434 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
435 if ( newCost == Cost::infinity ) {
436 return;
437 } // if
438 c += newCost;
439 } // while
440 if ( destIt != destAsTuple->types.end() ) {
441 cost = Cost::infinity;
442 } else {
443 cost = c;
444 } // if
445 } // if
446 }
447
448 void ConversionCost::postvisit( const VarArgsType * ) {
449 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
450 cost = Cost::zero;
451 }
452 }
453
454 void ConversionCost::postvisit( const ZeroType * ) {
455 if ( dynamic_cast< const ZeroType * >( dest ) ) {
456 cost = Cost::zero;
457 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
458 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
459 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
460 if ( tableResult == -1 ) {
461 cost = Cost::unsafe;
462 } else {
463 cost = Cost::zero;
464 cost.incSafe( tableResult + 1 );
465 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
466 } // if
467 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
468 cost = Cost::zero;
469 cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
470 } // if
471 }
472
473 void ConversionCost::postvisit( const OneType * ) {
474 if ( dynamic_cast< const OneType * >( dest ) ) {
475 cost = Cost::zero;
476 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
477 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
478 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
479 if ( tableResult == -1 ) {
480 cost = Cost::unsafe;
481 } else {
482 cost = Cost::zero;
483 cost.incSafe( tableResult + 1 );
484 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
485 } // if
486 } // if
487 }
488
489namespace {
490 # warning For overload resolution between the two versions.
491 int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
492 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
493 return ptrsAssignable( t1, t2, env );
494 }
495 Cost localConversionCost(
496 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
497 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
498 ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
499}
500
501Cost conversionCost(
502 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
503 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
504) {
505 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
506 if ( const ast::EqvClass * eqv = env.lookup( *inst ) ) {
507 if ( eqv->bound ) {
508 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
509 } else {
510 return Cost::infinity;
511 }
512 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
513 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
514 assertf( type, "Unexpected typedef." );
515 if ( type->base ) {
516 return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
517 }
518 }
519 }
520 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
521 return Cost::zero;
522 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
523 return Cost::safe;
524 } else if ( const ast::ReferenceType * refType =
525 dynamic_cast< const ast::ReferenceType * >( dst ) ) {
526 return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
527 } else {
528 return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
529 }
530}
531
532static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
533 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
534 PtrsCalculation func ) {
535 if ( 0 < diff ) {
536 Cost cost = convertToReferenceCost(
537 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
538 srcIsLvalue, (diff - 1), symtab, env, func );
539 cost.incReference();
540 return cost;
541 } else if ( diff < -1 ) {
542 Cost cost = convertToReferenceCost(
543 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
544 srcIsLvalue, (diff + 1), symtab, env, func );
545 cost.incReference();
546 return cost;
547 } else if ( 0 == diff ) {
548 const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
549 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
550 if ( srcAsRef && dstAsRef ) {
551 ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
552 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
553 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
554 srcAsRef->base, dstAsRef->base, symtab, env ) ) {
555 if ( tq1 == tq2 ) {
556 return Cost::zero;
557 } else {
558 return Cost::safe;
559 }
560 } else {
561 int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
562 if ( 0 < assignResult ) {
563 return Cost::safe;
564 } else if ( assignResult < 0 ) {
565 return Cost::unsafe;
566 }
567 }
568 } else {
569 return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
570 }
571 } else {
572 assert( -1 == diff );
573 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
574 assert( dstAsRef );
575 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
576 if ( srcIsLvalue ) {
577 if ( src->qualifiers == dstAsRef->base->qualifiers ) {
578 return Cost::reference;
579 } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
580 return Cost::safe;
581 } else {
582 return Cost::unsafe;
583 }
584 } else if ( dstAsRef->base->is_const() ) {
585 return Cost::safe;
586 } else {
587 return Cost::unsafe;
588 }
589 }
590 }
591 return Cost::infinity;
592}
593
594Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
595 bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
596 PtrsCalculation func ) {
597 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
598 return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
599}
600
601void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
602 (void)voidType;
603 cost = Cost::infinity;
604}
605
606void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
607 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
608 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
609 if ( tableResult == -1 ) {
610 cost = Cost::unsafe;
611 } else {
612 cost = Cost::zero;
613 cost.incSafe( tableResult );
614 cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
615 }
616 } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
617 // xxx - not positive this is correct, but appears to allow casting int => enum
618 const ast::EnumDecl * decl = (dynamic_cast< const ast::EnumInstType * >( dst ))->base.get();
619 if ( decl->base ) {
620 cost = Cost::infinity;
621 } else {
622 cost = Cost::unsafe;
623 } // if
624 }
625}
626
627void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
628 if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
629 ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
630 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
631 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
632 pointerType->base, dstAsPtr->base, symtab, env ) ) {
633 if ( tq1 == tq2 ) {
634 cost = Cost::zero;
635 } else {
636 cost = Cost::safe;
637 }
638 } else {
639 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
640 if ( 0 < assignResult && tq1 <= tq2 ) {
641 if ( tq1 == tq2 ) {
642 cost = Cost::safe;
643 } else {
644 cost = Cost::safe + Cost::safe;
645 }
646 } else if ( assignResult < 0 ) {
647 cost = Cost::unsafe;
648 } // else Cost::infinity
649 }
650 }
651}
652
653void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
654 (void)arrayType;
655}
656
657void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
658 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
659
660 cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
661 if ( refType->base->qualifiers == dst->qualifiers ) {
662 cost.incReference();
663 } else if ( refType->base->qualifiers < dst->qualifiers ) {
664 cost.incSafe();
665 } else {
666 cost.incUnsafe();
667 }
668}
669
670void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
671 (void)functionType;
672}
673
674void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
675 (void)enumInstType;
676 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
677 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
678 if ( cost < Cost::unsafe ) {
679 cost.incSafe();
680 }
681}
682
683void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
684 (void)traitInstType;
685}
686
687void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
688 if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) {
689 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
690 } else if ( const ast::TypeInstType * dstAsInst =
691 dynamic_cast< const ast::TypeInstType * >( dst ) ) {
692 if ( *typeInstType == *dstAsInst ) {
693 cost = Cost::zero;
694 }
695 } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
696 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
697 assertf( type, "Unexpected typedef.");
698 if ( type->base ) {
699 cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
700 }
701 }
702}
703
704void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
705 Cost c = Cost::zero;
706 if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
707 auto srcIt = tupleType->types.begin();
708 auto dstIt = dstAsTuple->types.begin();
709 auto srcEnd = tupleType->types.end();
710 auto dstEnd = dstAsTuple->types.end();
711 while ( srcIt != srcEnd && dstIt != dstEnd ) {
712 Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
713 if ( newCost == Cost::infinity ) {
714 return;
715 }
716 c += newCost;
717 }
718 if ( dstIt != dstEnd ) {
719 cost = Cost::infinity;
720 } else {
721 cost = c;
722 }
723 }
724}
725
726void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
727 (void)varArgsType;
728 if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
729 cost = Cost::zero;
730 }
731}
732
733void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
734 (void)zeroType;
735 if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
736 cost = Cost::zero;
737 } else if ( const ast::BasicType * dstAsBasic =
738 dynamic_cast< const ast::BasicType * >( dst ) ) {
739 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
740 if ( -1 == tableResult ) {
741 cost = Cost::unsafe;
742 } else {
743 cost = Cost::zero;
744 cost.incSafe( tableResult + 1 );
745 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
746 }
747 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
748 cost = Cost::zero;
749 // +1 for zero_t ->, +1 for disambiguation
750 cost.incSafe( maxIntCost + 2 );
751 }
752}
753
754void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
755 (void)oneType;
756 if ( dynamic_cast< const ast::OneType * >( dst ) ) {
757 cost = Cost::zero;
758 } else if ( const ast::BasicType * dstAsBasic =
759 dynamic_cast< const ast::BasicType * >( dst ) ) {
760 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
761 if ( -1 == tableResult ) {
762 cost = Cost::unsafe;
763 } else {
764 cost = Cost::zero;
765 cost.incSafe( tableResult + 1 );
766 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
767 }
768 }
769}
770// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
771
772} // namespace ResolvExpr
773
774// Local Variables: //
775// tab-width: 4 //
776// mode: c++ //
777// compile-command: "make install" //
778// End: //
Note: See TracBrowser for help on using the repository browser.