-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add C11 generic support #48
Conversation
Nice to finally see progress with this! This should probably work in most reasonable cases. It simply takes the union of all attributes (we handle qualifiers such as
Also, I think this Lval-Conversion that cppreference mentions also needs to be taken into account. I added a test that highlights both issues: Lines 1 to 27 in 50c02c9
GCC (via Godbolt) and Clang (via Godbolt) handle this correctly and output |
It is the closest thing to compatible types that I found in CIL. Is there anything more correct? The notion of compatible types is not new with generics, the same exact relation is used for types between different translation units and Thus (Unsurprisingly CIL contains two implementations for |
Maybe there is. But what CIL (and we in Goblint) try here is not exactly implement the C11 standard, but we are (very often) more relaxed in order to handle pre C11 code (C99, or ANSI) or allow things that are GCCism even if they are not in accordance to the standard; So it may very well be that - despite not doing exactly what the standard requires - the implementation does the correct things in all the places where it was used before we added support for generics?
So, if we look at the example above, compliant behavior is to match #define type3(x) _Generic((x), int:1, const int:2, default:0)
if(type3(v_intconst) != 1) { E(7); } If CIL does insert such a cast to The relevant definition for lvalue conversions btw is in 6.3.2.1:
So the way I would read this, this includes usage in the control expression of a generic expression, no? |
I looked at the other uses of Lines 1669 to 1670 in 041c7cf
Lines 4568 to 4570 in 041c7cf
And the type returned by combineTypes is actually what is called composite type in the standard and can only be constructed from two compatible types.
But you're probably right that the existing process is too forgiving for type qualifiers. C11 6.2.7.2 just says:
So CIL is allowing some of this undefined behavior. But the way it currently is implemented (union of attributes, which contain qualifiers) is nonsense: if one translation unit specifies a global as I'll try to add some extra type qualifier attribute checks to |
@michael-schwarz How is one supposed to run the tests locally? If I use
which actually is an expected failure (?). The exact same command on CI somehow only prints concise output: https://github.com/goblint/cil/runs/3567221712#step:11:538 and none of this confusing crap. EDIT: I figured it out. If any test fails, then I made a small change to not dump the whole raw log by default like that. |
If you are interested in only one specific tests you can also (provided you have done the
|
Normal const attribute will be preseved (not stripped from locals), such that type compatibility (e.g. for generic) is still correct. Must print some consts because otherwise the whole testing framework fails since it assumes CIL will keep some consts for GCC.
I tried to fix this final issue and it turned out to be much harder than I thought. First, I thought I could just introduce a global mutable CIL option, which controls whether to strip
Second, I tried something very naive: keep the Third and (hopefully) final, I came up with the idea of separating the |
(* Pick type for string literals *) | ||
stringLiteralType := if !M.theMachine.M.const_string_literals then | ||
charConstPtrType | ||
else | ||
charPtrType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is removing this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, looks like this is an MSVC thing, which we will no longer support anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it was actually supposed to be a GCC thing, but it didn't even match the typing behavior of GCC: #48 (comment).
@@ -403,6 +404,7 @@ and get_operator exp = | |||
| TYPE_SIZEOF _ -> ("", 16) | |||
| EXPR_ALIGNOF exp -> ("", 16) | |||
| TYPE_ALIGNOF _ -> ("", 16) | |||
| GENERIC _ -> ("", 16) (* TODO: is this right? *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this TODO resolved now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect not, but I don't know what it's precedence is even supposed to be because it's not even listed here: https://en.cppreference.com/w/c/language/operator_precedence.
Also, I'm not sure the rest are right either. Most of the additions have been copy-pasted all with precedence 16, but that doesn't match at all with the precedence table comment above or the table on cppref.
Probably after merging |
CHANGES: * Wrap library into `GoblintCil` module (goblint/cil#107). * Remove all MSVC support (goblint/cil#52, goblint/cil#88). * Port entire build process from configure/make to dune (goblint/cil#104). * Add C11 `_Generic` support (goblint/cil#48). * Add C11 `_Noreturn` support (goblint/cil#58). * Add C11 `_Static_assert` support (goblint/cil#62). * Add C11 `_Alignof` support (goblint/cil#66). * Add C11 `_Alignas` support (goblint/cil#93, goblint/cil#108). * Add partial C11 `_Atomic` support (goblint/cil#61). * Add `_Float32`, `_Float64`, `_Float32x` and `_Float64x` type support (goblint/cil#8, goblint/cil#60). * Add Universal Character Names, `char16_t` and `char32_t` type support (goblint/cil#80). * Change locations to location spans and add additional expression locations (goblint/cil#51). * Add synthetic marking for CIL-inserted statement locations (goblint/cil#98). * Expose list of files from line control directives (goblint/cil#73). * Add parsed location transformation hook (goblint/cil#89). * Use Zarith for integer constants (goblint/cil#47, goblint/cil#53). * Fix constant folding overflows (goblint/cil#59). * Add option to disable constant branch removal (goblint/cil#103). * Add standalone expression parsing and checking (goblint/cil#97, goblint/cil#96). * Improve inline function merging (goblint/cil#72, goblint/cil#85, goblint/cil#84, goblint/cil#86). * Fix some attribute parsing cases (goblint/cil#71, goblint/cil#75, goblint/cil#76, goblint/cil#77). * Fix global NaN initializers (goblint/cil#78, goblint/cil#79). * Fix `cilly` binary installation (goblint/cil#99, goblint/cil#100, goblint/cil#102). * Remove batteries dependency to support OCaml 5 (goblint/cil#106).
CHANGES: * Wrap library into `GoblintCil` module (goblint/cil#107). * Remove all MSVC support (goblint/cil#52, goblint/cil#88). * Port entire build process from configure/make to dune (goblint/cil#104). * Add C11 `_Generic` support (goblint/cil#48). * Add C11 `_Noreturn` support (goblint/cil#58). * Add C11 `_Static_assert` support (goblint/cil#62). * Add C11 `_Alignof` support (goblint/cil#66). * Add C11 `_Alignas` support (goblint/cil#93, goblint/cil#108). * Add partial C11 `_Atomic` support (goblint/cil#61). * Add `_Float32`, `_Float64`, `_Float32x` and `_Float64x` type support (goblint/cil#8, goblint/cil#60). * Add Universal Character Names, `char16_t` and `char32_t` type support (goblint/cil#80). * Change locations to location spans and add additional expression locations (goblint/cil#51). * Add synthetic marking for CIL-inserted statement locations (goblint/cil#98). * Expose list of files from line control directives (goblint/cil#73). * Add parsed location transformation hook (goblint/cil#89). * Use Zarith for integer constants (goblint/cil#47, goblint/cil#53). * Fix constant folding overflows (goblint/cil#59). * Add option to disable constant branch removal (goblint/cil#103). * Add standalone expression parsing and checking (goblint/cil#97, goblint/cil#96). * Improve inline function merging (goblint/cil#72, goblint/cil#85, goblint/cil#84, goblint/cil#86). * Fix some attribute parsing cases (goblint/cil#71, goblint/cil#75, goblint/cil#76, goblint/cil#77). * Fix global NaN initializers (goblint/cil#78, goblint/cil#79). * Fix `cilly` binary installation (goblint/cil#99, goblint/cil#100, goblint/cil#102). * Remove batteries dependency to support OCaml 5 (goblint/cil#106).
Part of issue #13.
This PR cherry-picks the generic related commits out of #24, where they have been committed together with unrelated C11 features...
And then it's mostly rewritten according to #24 (review):
Generic
is removed from CIL and resolved byCabs2cil
, so it's completely transparent downstream (e.g. Goblint).combineTypes
, which seems to be the right thing (it raises on incompatibility).void
type for it.