source: src/ResolvExpr/ConversionCost.cc@ 9317419

ADT ast-experimental
Last change on this file since 9317419 was 5bf3976, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Header Clean-Up: Created new headers for new AST typeops and moved declarations.

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