-
Notifications
You must be signed in to change notification settings - Fork 289
Expand file tree
/
Copy pathcpp_typecheck_fargs.cpp
More file actions
146 lines (119 loc) · 3.43 KB
/
cpp_typecheck_fargs.cpp
File metadata and controls
146 lines (119 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*******************************************************************\
Module: C++ Language Type Checking
Author: Daniel Kroening, [email protected]
\*******************************************************************/
/// \file
/// C++ Language Type Checking
#include "cpp_typecheck_fargs.h"
#include <util/std_types.h>
#include "cpp_typecheck.h"
bool cpp_typecheck_fargst::has_class_type() const
{
for(const auto &op : operands)
{
if(op.type().id() == ID_struct)
return true;
}
return false;
}
void cpp_typecheck_fargst::build(
const side_effect_expr_function_callt &function_call)
{
in_use=true;
operands = function_call.arguments();
}
bool cpp_typecheck_fargst::match(
const code_typet &code_type,
unsigned &distance,
cpp_typecheckt &cpp_typecheck) const
{
distance=0;
exprt::operandst ops=operands;
const code_typet::parameterst ¶meters=code_type.parameters();
if(parameters.size()>ops.size())
{
// Check for default values.
ops.reserve(parameters.size());
for(std::size_t i=ops.size(); i<parameters.size(); i++)
{
const exprt &default_value=
parameters[i].default_value();
if(default_value.is_nil())
return false;
ops.push_back(default_value);
}
}
else if(parameters.size()<ops.size())
{
// check for ellipsis
if(!code_type.has_ellipsis())
return false;
}
exprt::operandst::iterator it=ops.begin();
for(const auto ¶meter : parameters)
{
// read
// http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/
// com.ibm.xlcpp8a.doc/language/ref/implicit_conversion_sequences.htm
//
// The following are the three categories of conversion sequences
// in order from best to worst:
// * Standard conversion sequences
// * User-defined conversion sequences
// * Ellipsis conversion sequences
DATA_INVARIANT(it != ops.end(), "arguments and parameters must match");
const exprt &operand=*it;
typet type=parameter.type();
#if 0
// unclear, todo
if(is_reference(operand.type()))
std::cout << "O: " << operand.pretty() << '\n';
assert(!is_reference(operand.type()));
#endif
// "this" is a special case -- we turn the pointer type
// into a reference type to do the type matching
if(it == ops.begin() && parameter.get_this())
{
type.set(ID_C_reference, true);
type.set(ID_C_this, true);
}
unsigned rank=0;
exprt new_expr;
#if 0
std::cout << "C: " << cpp_typecheck.to_string(operand.type())
<< " -> " << cpp_typecheck.to_string(parameter.type())
<< '\n';
#endif
// can we do the standard conversion sequence?
if(cpp_typecheck.implicit_conversion_sequence(
operand, type, new_expr, rank))
{
// ok
distance+=rank;
#if 0
std::cout << "OK " << rank << '\n';
#endif
}
else if(
operand.id() == ID_initializer_list && cpp_typecheck.cpp_is_pod(type) &&
operand.operands().size() == 1 &&
cpp_typecheck.implicit_conversion_sequence(
to_unary_expr(operand).op(), type, new_expr, rank))
{
distance += rank;
}
else
{
#if 0
std::cout << "NOT OK\n";
#endif
return false; // no conversion possible
}
++it;
}
// we may not have used all operands
for( ; it!=ops.end(); ++it)
// Ellipsis is the 'worst' of the conversion sequences
distance+=1000;
return true;
}