Summary
##sys#foreign-pointer-argument is declared to accept a pointer only, but is possibly invoked with a boolean
Metadata
- Id: 89f2043fbd4c4ce7a76254221532b642a9e506a8
- Trac id: 847
- Type: defect
- Reporter: sjamaan
- Owner:
- Cc:
- Status: closed
- Component: scrutinizer
- Estimated difficulty:
- Resolution: fixed
- Priority: major
- Milestone: 4.9.0
- Version: 4.7.x
- Changetime: 2014-02-01 17:18:59 UTC
- Created: 2012-05-16 18:11:51 UTC
- Keywords:
Description
When you use let-location or define-foreign-variable and declare a pointer type, you can set it to a NULL value by setting it to #f in Scheme and this works correctly. However, the scrutinizer thinks that's bad:
$ cat test.scm (define-foreign-variable bar c-pointer) (set! bar #f) (let-location ((x c-pointer #f)) ((foreign-lambda void "printf" c-string c-pointer) "%p\n" x)) $ csc -scrutinize test.scm Warning: at toplevel: (test.scm:3) in procedure call to `##sys#foreign-pointer-argument', expected argument #1 of type `pointer', but was given an argument of type `boolean' Warning: at toplevel: (test.scm:5) in procedure call to `##sys#foreign-pointer-argument', expected argument #1 of type `pointer', but was given an argument of type `boolean'
The underlying problem is that ##sys#foreign-pointer-argument is declared as accepting only pointer types (which is correct, it will barf otherwise), but the initializer/set value is #f, a boolean which is allowed as a value representing a NULL pointer. The if check in library.scm:1077 takes care of this situation, but the scrutinizer is unable to verify that the boolean isn't #t when it passes the if and takes the ##sys#foreign-pointer-argument branch (and it might be!). This output be seen more clearly when calling "csc -debug 2 test.scm".
We could do a few things here:
1) Add a ##core#the assertion that states the argument is definitely a pointer. That kind of kills the scrutinizer's effectiveness at warning, moving the error to runtime (it's also incorrect in case anything else is passed). 2) Map #t to #f (a NULL pointer eventually in the C translation). That's inconsistent with the rest of core. 3) Map #t to an error. This still moves the error to a runtime one but keeps the scrutinizer warnings for all non-boolean types. 4) Keep it the way it is. That will give bogus warnings on this kind of code. 5) Remove ##sys#foreign-pointer-argument from types.db or change it to accept a boolean. The former again gets rid of the advantage of having the scrutinizer and the latter is blatantly incorrect. 6) Change the ##sys#foreign-pointer-argument to accept booleans and only return C_SCHEME_FALSE and barf on C_SCHEME_TRUE. 7) Augment the type system with yet another special case for #f, adding a "false" type that is a subtype of "boolean".
I don't know which option I like most (or dislike least). 7 is definitely the most "thorough" option, similar to the special handling of null, pair and list(-of) types, but it raises the complexity of the scrutinizer another notch. Other acceptable solutions would probably either be 3 or 6, which both basically come down to the same thing. I think whatever we do, we should probably postpone it until after the next release unless someone comes up with a clever, noninvasive alternative of course :)
Changes and comments
[2014-02-01 17:18:59 UTC] sjamaan changed status from new to closed
[2014-02-01 17:18:59 UTC] sjamaan set resolution to fixed
[2014-02-01 17:18:59 UTC] sjamaan wrote:
Fixed by ddb2b635013492c660b017b1cc29118e9d73165d