Skip to content

Commit 4c699cf

Browse files
Refine symbol well-formedness checks to handle special cases
The symbol naming check added in df616e4 attempts to assert that the 'base_name' of a symbol is a suffix of that symbol's 'name'. In general, this should be the case, but there are certain classes of symbols where this does not currently hold. This commit adds special cases to handle: * Type symbols that are typedefs or tags * Symbols that have been renamed by the linker With these special cases handled, it is possible to run the CORE regression tests with --validate-goto-model enabled.
1 parent feb6e5d commit 4c699cf

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

src/util/symbol.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include "source_location.h"
1414
#include "std_expr.h"
15+
#include "string_utils.h"
1516
#include "suffix.h"
1617

1718
/// Dump the state of a symbol object to a given output stream.
@@ -137,11 +138,62 @@ bool symbolt::is_well_formed() const
137138
// Well-formedness criterion number 2 is for a symbol
138139
// to have it's base name as a suffix to it's more
139140
// general name.
141+
140142
// Exception: Java symbols' base names do not have type signatures
141143
// (for example, they can have name "someclass.method:(II)V" and base name
142144
// "method")
143145
if(!has_suffix(id2string(name), id2string(base_name)) && mode != ID_java)
144-
return false;
146+
{
147+
bool criterion_must_hold = true;
148+
149+
// There are some special cases where this criterion doesn't hold, check
150+
// to see if we have one of those cases
151+
152+
if(is_type)
153+
{
154+
// Typedefs
155+
if(
156+
type.find(ID_C_typedef).is_not_nil() &&
157+
type.find(ID_C_typedef).id() == base_name)
158+
{
159+
criterion_must_hold = false;
160+
}
161+
162+
// Tag types
163+
if(type.find(ID_tag).is_not_nil() && type.find(ID_tag).id() == base_name)
164+
{
165+
criterion_must_hold = false;
166+
}
167+
}
168+
169+
// Linker renaming may have added $linkN suffixes to the name, and other
170+
// suffixes such as #return_value may have then be subsequently added.
171+
// Strip out the first $linkN substring and then see if the criterion holds
172+
const auto &unstripped_name = id2string(name);
173+
const size_t dollar_link_start_pos = unstripped_name.find("$link");
174+
175+
if(dollar_link_start_pos != std::string::npos)
176+
{
177+
size_t dollar_link_end_pos = dollar_link_start_pos + 5;
178+
while(isdigit(unstripped_name[dollar_link_end_pos]))
179+
{
180+
++dollar_link_end_pos;
181+
}
182+
183+
const auto stripped_name =
184+
unstripped_name.substr(0, dollar_link_start_pos) +
185+
unstripped_name.substr(dollar_link_end_pos, std::string::npos);
186+
187+
if(has_suffix(stripped_name, id2string(base_name)))
188+
criterion_must_hold = false;
189+
}
190+
191+
if(criterion_must_hold)
192+
{
193+
// For all other cases this criterion should hold
194+
return false;
195+
}
196+
}
145197

146198
return true;
147199
}

0 commit comments

Comments
 (0)