sourcepawn icon indicating copy to clipboard operation
sourcepawn copied to clipboard

[Bug]: IsValidHandle does not trigger deprecation warning

Open Rainyan opened this issue 3 months ago • 3 comments

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

Rainyan avatar Sep 02 '25 16:09 Rainyan

Sorry, this might actually more belong to the sourcepawn repo(?) Possibly related: https://github.com/alliedmodders/sourcepawn/issues/409 ?

Rainyan avatar Sep 02 '25 17:09 Rainyan

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

Headline avatar Sep 19 '25 18:09 Headline

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.

dvander avatar Sep 23 '25 02:09 dvander