-
Notifications
You must be signed in to change notification settings - Fork 72
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
Implement warning 210 #440
base: dev
Are you sure you want to change the base?
Conversation
5022aea
to
76a7de5
Compare
It would be much easier to blacklist uses, rather than whitelist them. I don't think there are any others besides these: if (uninitialised) // warning FuncNotPassedByRef(uninitialised) // warning lvalue = uninitialised; // warning Basically only the places where the value is retrieved once and not modified. This may already be what you have, but best to check the two are equivalent. What would this PR do for: FuncPassedByRef(uninitialised) ? |
76a7de5
to
f98d3f9
Compare
Cleaned up the code and added a few workarounds to support detection of uninitialized arrays (previously the compiler was able to detect only single variables). I also made the compiler not issue warning 210 if an array is passed to a native function, because some of SA-MP natives are not const-correct.
|
There might be more complex uses, like these: if (initialized == 0 && uninitialized != 0) // warning FuncNotPassedByRef(initialized + uninitialized); // warning lvalue = initialized + uninitialized; // warning This PR makes the compiler issue warning 210 in all of the mentioned cases.
Depends on how exactly forward FuncPassedByRef(&par);
// ...
FuncPassedByRef(uninitialized); // no warnings (the symbol is treated as modified) forward FuncPassedByRef(const &par);
// ...
FuncPassedByRef(uninitialized); // warning 210 (the symbol is treated as read) forward FuncPassedByRef(arr[]);
// ...
FuncPassedByRef(uninitialized); // no warnings forward FuncPassedByRef(const arr[]);
// ...
FuncPassedByRef(uninitialized); // warning 210 native FuncPassedByRef(arr[]);
// ...
FuncPassedByRef(uninitialized); // no warnings native FuncPassedByRef(const arr[]);
// ...
FuncPassedByRef(uninitialized); // no warnings either, because not all SA-MP natives are const-correct |
This was fixed last year: https://github.com/sampctl/samp-stdlib/blob/master/a_players.inc#L656 |
But still, not everyone uses sampctl or manually installs modified includes from that repo. |
I don't think we should worry about people not using the latest versions of things on the latest version of something. If they want to use the new compiler, but not the new includes, that's on them. We shouldn't penalise those who do upgrade (by omitting diagnostics) for the sake of those who don't. Yes, another warning did the same, before we fixed the includes. It should probably now be restricted more. |
Err... no, it did so after the includes were fixed. Anyway, I made a PR that re-enables warning 239 for natives. It only modifies one line of code, so I believe it shouldn't take a lot of time to review and merge it. After it's merged, I'll re-enable warning 210 for natives in this PR too. |
f98d3f9
to
f14a3ea
Compare
I merged this and had a play. It is somewhat telling that when I tested this on YSI with tests enabled almost every warning instance was I found many instances of false positives in That's extremely common in YSI. Basically every y_amx use looks like this.
This one is questionable, since the modification is in assembly. Were you to ignore that I'd entirely understand. Another highly questionable one. All that variable does is exist to be destructed. Should destructors trigger this warning? I don't know. This one can be silenced with There are a fair number in the y_foreach tests, which at first I wasn't sure what to do about, since the count arrays are default zeroed, and it isn't a mistake. But most of them look like this: That's an assertation that an array which should be initially empty, is. I guess that's fine to have a warning like this on since I'm checking that nothing truly horrible has happened in compilation. But there are also many other places with arrays (especially globals) declared and left as-is. The problem is that no explicit initialisation is not only common, but valid and well defined. |
Also a definite bug. If this PR is merged to HEAD now, I get:
On: I do not (and shouldn't) get it before merging this code. |
Must be due to a workaround I used for arrays (which I had to add because function |
f14a3ea
to
a50b791
Compare
* A variable is defined as a loop counter inside a 'for' loop. * A variable is incremented/decremented using the '++'/'--' operator.
a50b791
to
8462b80
Compare
I made the compiler not issue warning 210 if a variable is incremented or decremented with
I intentionally didn't apply the same exception for
Umm... but I did make an exception for assembly? The warning probably comes from
I think the real problem here is that in this case the compiler doesn't issue a warning about an array being unused because it has a destructor.
AFAIK, the official documentation (pawn-lang.pdf) only briefly mentions that
It even tells that there might be false-positives due to the way how the compiler works. Another question is why this warning ended up unimplemented? It always seemed strange to me that the compilers for a lot of other languages such as C, C++ (MSVC, GCC, Clang), Pascal (FPC) etc. already have this basic diagnostic, and Pawn - "a robust language with a compiler that performs a maximum of static checks" - for some reason doesn't have it.
It seems that I forgot to mark arrays as |
This issue has been automatically marked as stale because it has not had recent activity. |
I'm still slightly wary of this, so I'd like to know what others think. @Zeex @Southclaws @YashasSamaga etc? I just checked again and there are several places in YSI that kick up warnings in valid code even with the latest version. The cause of all those warnings is that Maybe it should be restricted only to variables whose first use is a read outside of a loop in which they are modified. At least to begin with. This is almost certainly not what is intended: new a;
Func(a); While this is more likely correct: new a;
while (a < 11)
{
Func(a);
a = a * 3 - 1;
} The first you can just use a constant, the second you can't catch every possible way in which a variable might be modified. Just see that it's written in the loop and thus assume it is written at every point in the loop. |
This issue has been automatically marked as stale because it has not had recent activity. |
Sounds doable, but I'll need #533 being merged first, as it allows the compiler to memoize the compound statement nesting level for loops - without that there would be no way to determine if the variable was defined outside of the current loop or inside it. |
Done |
This issue has been automatically marked as stale because it has not had recent activity. |
I had another look at merging this one today. It's still quite controversial, simply due to the number of new warnings thrown up for idiomatic pawn code, so I'm not going to merge it unless other people chime in. Having said that, a few of the tests after rebase are failing:
That warning doesn't even seem to make sense. This warning:
Is also not given any more, however, it's entirely possible that's my fault for a poor rebase. The other warnings in tests were easily fixed by adding some initialisations. |
This issue has been automatically marked as stale because it has not had recent activity. |
What this PR does / why we need it:
This PR implements
warning 210: possible use of symbol before initialization: "(identifier)"
.Although the text for this warning is present in
sc5.c
since the times when the language was called Small, for some reason the warning itself was never implemented.This diagnostic should help to detect hidden bugs and oversights in scripts, which could be useful for both novice and experienced scripters.
For example, here's an interesting bug I was able to find in NGRP's code using this new diagnostic:
https://github.com/NextGenerationGamingLLC/SA-MP-Development/blob/a059abaebda0f2dff3c2e0f95ee4c9c5696406c7/GMs/includes/timers.pwn#L2898
Variable
fExpHealth
is used inside anif
expression before being assigned a value. This is obviously a typo; the author of this code intended to usefVehicleHealth
instead.Some other bugs I was able to find:
Of course, I realize that some scripters tend to use
new var;
as a shortcut fornew var = 0;
, especially in loops, which may cause false-positive "warning 210" messages.This is why I disabled this warning for the following cases:
for
loop;++
/--
operator).const
qualifier.This should decrease the number of false-positives to a reasonable minimum and allow the user to concentrate on the actual bugs found with this new diagnostic.
Which issue(s) this PR fixes:
What kind of pull this is:
Additional Documentation: