source: src/ResolvExpr/ConversionCost.cc@ df00c78

ADT ast-experimental pthread-emulation
Last change on this file since df00c78 was fc134a48, checked in by JiadaL <j82liang@…>, 3 years ago

Implement the struct enum

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