source: src/ResolvExpr/ConversionCost.cc@ 22f94a4

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 22f94a4 was 22f94a4, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Merge branch 'master' into new-ast

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