-
Notifications
You must be signed in to change notification settings - Fork 88
Open
Labels
Description
C23 has relaxed rules for struct type compatibility making the following code snippet legal:
typedef void (*func_t)(void);
struct A {
func_t f;
};
void test1(struct A {
func_t f;
} *b) {
b->f();
}
void dummy() {}
int main() {
struct A arg = {dummy};
test1(&arg);
return 0;
}Goblint (revision e816b4a) fails to recognize that b->f is initialized to dummy and outputs
[Warning][Unsound][Call] No suitable function to be called at call site. Continuing with state before call
C23 standard (section 6.2.7) specifies:
Moreover, two complete structure, union, or enumerated types declared with the
same tag are compatible if members satisfy the following requirements:
— there shall be a one-to-one correspondence between their members such that each pair of
corresponding members are declared with compatible types;
— if one member of the pair is declared with an alignment specifier, the other is declared with an
equivalent alignment specifier;
— and, if one member of the pair is declared with a name, the other is declared with the same
name
More discussion is also available in the following proposal.
This issue has surfaced when trying to analyze rsync version from AnalyzeThat. The linked code is in fact even more liberal in using pointers to incompatible struct types, as it declares these struct types with different tags (for example, see the type of the first parameter in the call to deflateInit_ from compress2).
Reactions are currently unavailable