-
Notifications
You must be signed in to change notification settings - Fork 75
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
Refactor and generalize warning system to message system #338
Conversation
…less of dbg.debug
While doing this, I discovered that So all warnings have a location, but the non-each vs each just determines how they're deduplicated. Since both kinds include a location, it feels like that should be the default and called So my question is: do we actually want the previous The current refactored state preserves all the old behavior for all message severities, not just warnings, but while we're at it, it would also make sense to rethink this. Currently the message record has two different locations to accommodate the old behavior ( |
src/analyses/base.ml
Outdated
@@ -803,13 +801,13 @@ struct | |||
match (eval_rv a gs st n) with | |||
| `Address adr -> | |||
(if AD.is_null adr | |||
then M.warn_each ~must:true ~warning:(M.Warning.Behavior.Undefined.nullpointer_dereference ()) () | |||
then M.error_each ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[M.Tag.CWE 476] "Must dereference NULL pointer" |
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.
Maybe it makes sense to abstract warnings that have multiple calls in order to avoid inconsistencies.
A nullpointer_dereference
warning should include its CWE and text.
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'm not sure how necessary this would be because there shouldn't be duplication in warnings in the first place: each one should be emitted by an analysis responsible for it. And even here there are subtle differences between the two: the error is for a must-dereference (mentioned in the message) and the warning is for a may-dereference (mentioned in the message).
And coupling categories with CWEs etc is precisely what we want to avoid in some other places, for example integer overflows. The complete messaging for those is not yet there, but the idea is as follows. Unlike signed overflows, unsigned overflows are not undefined behavior, but they are still considered under the same CWE. While signed overflows should also have an undefined behavior category tag in addition to the integer overflow one. And to be extra precise, there's separate CWEs for overflow and underflow.
So all the subtle variations intentionally should have different tags (and probably messages).
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.
And even here there are subtle differences between the two: the error is for a must-dereference (mentioned in the message) and the warning is for a may-dereference (mentioned in the message).
The text then duplicates the information given by warn/error.
And coupling categories with CWEs etc is precisely what we want to avoid in some other places, for example integer overflows.
Makes sense, but there you can still have different calls.
I'm not sure how necessary this would be because there shouldn't be duplication in warnings in the first place: each one should be emitted by an analysis responsible for it.
The two calls here are identical besides warn/error.
There may be several analysis reporting the same warning.
Maybe it's not that common. I just spotted this bit and imagined it may be a source of duplicated code.
But it's also not clear how to best abstract it. Could introduce warn/error functions that take pre-defined message records.
It may also be worth thinking about whether it's viable to define all warnings/errors (not debug) in one place (similar to defaults.ml
) and then just reference them. This would avoid duplication and give a list of everything we report.
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.
The text then duplicates the information given by warn/error.
This is true for must/may, but it's probably for the user's benefit, such they don't have to deduce it from whether it's an error or just a warning. The exact difference between errors and warnings might be analysis-dependent though and more general distinction than must/may. Attaching must/may to every message also doesn't make sense.
There may be several analysis reporting the same warning.
The fact that different analyses report the same thing sounds like a duplication in the first place though.
But it's also not clear how to best abstract it. Could introduce warn/error functions that take pre-defined message records.
It may also be worth thinking about whether it's viable to define all warnings/errors (not debug) in one place (similar todefaults.ml
) and then just reference them.
This would be a possible direction indeed if we want to very strictly enumerate all our warnings, a la some compilers or analyzers which specify unique IDs for each warning type. But given that most of the messages still have unknown category and haven't been even properly reviewed or categorized broadly, I think that's too much of a stretch for now.
👍
My assumption was that it was intended as a 'fix warning and re-analyze' mode of using goblint. |
Indeed, deduplication by just message could be done as preprocessing for message display whereever needed. I guess it'd even be possible to implement a transformation that doesn't completely drop secondary messages but replaces them all with a single grouped message. Although even for going multithreaded, just reporting the first analyzed location is a bit weird because you may have two branches, which both go multithreaded, but then you'd only see a warning about one of them doing that, while it might look like through the other branch you don't. |
Yes, these 'dependent' warnings were another idea for this. |
Yes, this was a bad design decision. All sorts of filtering and ranking should happen after the analysis. Glancing over current usages of M.warn versus M.warn_each, it seems we are fairly random about it. I can see a couple of sensible usages, such as I was wondering if we should have some specific tag for "state transition" to assist future plans of filtering/grouping warnings, so then you could add that tag when getting rid of the warn cases, but since warn/warn_each are not used consistently and deliberately, we'll have to think that through anyway... |
Removing the old But if we want to then have a properly locationless warnings (unlike the old warnings which would print I guess it also might be possible to make |
I called it |
Yes, that's what I meant.
That would be the nicest solution. |
It would be more verbose though because that would be an optional Also it seemingly allows for a confusing combination where you can call it with |
This PR refactors #255 further.
Changes
string
-basedwarnings_table
with record-basedMessages.Table
which keeps all metadata.()
argument.string
argument withPretty
format. This makes it much nicer to insert data into message text, a laPrintf
and the existingtrace
functions.warn
, which used to contain location but deduplicate without it, and replace it withwarn_noloc
, which doesn't contain location at all.warn_each
, which has current location, towarn
as the most common case.Messages.current_context
(a laTracing.current_loc
etc). These context are completely abstract (Obj.t
) though, so they're not very useful with their integer (hash) representation, but that's a separate more general issue.bailwith
/Bailure
.Format
and its semantic tags for terminal colors.json-messages
result type for exporting all messages (with their metadata) to external tools, e.g. IDE integration.TODO
to_yojson
of messages further? Not now, if needed then later on master.warn
vswarn_each
? See Refactor and generalize warning system to message system #338 (comment).