[Bug]: IsValidHandle does not trigger deprecation warning
Prerequisites
- [x] I have checked that my issue doesn't exist yet in the issue tracker
Operating System and Version
Windows 11
Game / AppID and Version
N/A
SourceMod Version
1.11.0.6970
Metamod:Source Version
N/A
Version Verification
- [x] I have updated SourceMod to the latest version and the issue persists
- [x] I have updated SourceMod to the latest snapshot and the issue persists
- [x] I have updated Metamod:Source to the latest snapshot and the issue persists
Updated SourceMod Version
1.13.0.7251
Updated Metamod:Source Version
N/A
Description
The deprecated SourcePawn function IsValidHandle does not trigger compiler warning for SM version range 1.11-1.13.
Based on code docs at: https://github.com/alliedmodders/sourcemod/blob/512e7c37c10d8040e8ee7d914a51627295a8c5b0/plugins/include/handles.inc#L111-L129 I would expect to be warned against using this function, but that does not seem to occur with SM compilers outside the 1.8-1.10 range (I did not check for versions older than 1.8).
Is this an intended change where this function has become un-deprecated, but that un-deprecation is undocumented, or is this a problem with the compiler not correctly triggering the deprection warning for this SM compiler range?
Steps to Reproduce
Compile the following plugin:
#include <sourcemod>
public void OnPluginStart()
{
IsValidHandle(INVALID_HANDLE); // intentional no-op to test the deprecation warning of the func
}
What should happen:
- Compile output prints a deprecation warning
What actually happens:
- For SM compilers >=1.11, the deprecation warning is not printed
Relevant Log Output
SourcePawn Compiler 1.8.0.6050
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2015 AlliedModders LLC
.\ivh.sp(5) : warning 234: symbol "IsValidHandle" is marked as deprecated: Do not use this function.
Code size: 2960 bytes
Data size: 2220 bytes
Stack/heap size: 16384 bytes
Total requirements: 21564 bytes
1 Warning.
SourcePawn Compiler 1.9.0.6282
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC
.\ivh.sp(5) : warning 234: symbol "IsValidHandle" is marked as deprecated: Do not use this function.
Code size: 2960 bytes
Data size: 2220 bytes
Stack/heap size: 16384 bytes
Total requirements: 21564 bytes
1 Warning.
SourcePawn Compiler 1.10.0.6545
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
.\ivh.sp(5) : warning 234: symbol "IsValidHandle" is marked as deprecated: Do not use this function.
Code size: 3032 bytes
Data size: 2280 bytes
Stack/heap size: 16384 bytes
Total requirements: 21696 bytes
1 Warning.
SourcePawn Compiler 1.11.0.6970
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2021 AlliedModders LLC
Code size: 3532 bytes
Data size: 2280 bytes
Stack/heap size: 16452 bytes
Total requirements: 22264 bytes
SourcePawn Compiler 1.12.0.7210
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2024 AlliedModders LLC
Code size: 3532 bytes
Data size: 2280 bytes
Stack/heap size: 16452 bytes
Total requirements: 22264 bytes
SourcePawn Compiler 1.13.0.7251
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2024 AlliedModders LLC
Code size: 3532 bytes
Data size: 2280 bytes
Stack/heap size: 16452 bytes
Total requirements: 22264 bytes
Sorry, this might actually more belong to the sourcepawn repo(?) Possibly related: https://github.com/alliedmodders/sourcepawn/issues/409 ?
I took a look at this one, I'm not sure of the fix but I think I understand what's going on. Minimal reproducable example:
methodmap TestMap {
public native void TestNative();
};
#pragma deprecated wwwwwwwwwwwwwwwwwwwwww
native void DeprecatedFunc();
void main()
{
DeprecatedFunc();
}
the deprecated string is getting lexed as a part of Parser::parse_methodmap from Lexer::require_newline after the methodmap matches its final } - example stack
spcomp.exe!sp::cc::Lexer::HandleDirectives() Line 422 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:422)
spcomp.exe!sp::cc::Lexer::FindNextToken() Line 813 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:813)
spcomp.exe!sp::cc::Lexer::LexNewToken() Line 1589 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:1589)
spcomp.exe!sp::cc::Lexer::lex() Line 1576 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:1576)
spcomp.exe!sp::cc::Lexer::lex_tok() Line 345 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.h:345)
spcomp.exe!sp::cc::Lexer::peek_same_line() Line 2198 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:2198)
spcomp.exe!sp::cc::Lexer::require_newline(sp::cc::TerminatorPolicy policy) Line 2255 (b:\alliedmodders\sourcemod\sourcepawn\compiler\lexer.cpp:2255)
spcomp.exe!sp::cc::Parser::parse_methodmap() Line 1873 (b:\alliedmodders\sourcemod\sourcepawn\compiler\parser.cpp:1873)
The deprecated string then gets cleared after Parser::Parse is done with the tMETHODMAP case
Oh, yeah, this was completely busted by combining the lexer and preprocessor into a single pass. We are trying to tie some information (a deprecate string) to the next set of tokens (a function declaration). Anything tied to a token must be saved in the token queue. What's happening is that the lexer's readahead is populating the token queue way ahead of where we're actually parsing, so deprecate_ gets populated prematurely. And since deprecate_ is effectively a global, parsing a token earlier in the queue causes it to get cleared.
What I'd typically do here is synthesize a token into the queue. You can see an example of this in the "pragma unused" handling code. The synthesized token would be something like tSYN_PRAGMA_DEPRECATE, and then if we see this token in Parser::parse(), we'd update the deprecate_ state for the next top-level declaration.