DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

HLSL intrinsic will match everything and anything even forward declared template functions

Open Przemog1 opened this issue 1 month ago • 1 comments

Description Currently, HLSL intrinsics exist in the global namespace. When a developer defines their own functions or utilities without explicitly specifying a namespace, DXC implicitly prioritizes HLSL intrinsics. This can silently shadow user-defined symbols, and the compiler does not report namespace shadowing or ambiguous symbol resolution. This makes it harder to detect unintentional name conflicts and reduces clarity when reading or maintaining code.

HLSL intrinsics are matched even against forward-declared function templates with no body, including templates that are intentionally disabled via enable_if. Despite the template being non-viable and non-instantiable, the compiler still treats it as a valid overload candidate and then silently falls back to the intrinsic. This violates normal C++ overload resolution rules, where a SFINAE-disabled or non-defined template should not participate in overload resolution at all. This is not just an undesired name-lookup behavior - it is a compiler bug.

Also note that flags -Wshadow and -Wconversion have no effect.

Steps to Reproduce Threre are several issues:

  • https://godbolt.org/z/7zqxcEo6W - incorrectly chooses the HLSL intrinsic dot over the user-defined dot.
  • https://godbolt.org/z/vvz4TEoje - ::dot(a,b) on line 26 incorrectly picks dot from the myNs namespace. Note that it will pick the global dot when it is defined: https://godbolt.org/z/ePGr5Gn49
  • https://godbolt.org/z/dP983fGq6 - see comments
  • https://godbolt.org/z/K5sz43YWG - incorrectly chooses the HLSL intrinsic select over the user-defined select, even when select is called with template arguments but the intrinsic version is not templated. Can be switched using #define NO_BUG.
  • https://godbolt.org/z/vW4ocK3Yr - the HLSL select intrinsic is not templated, but the compiler prefers it over a user-defined template that shadows it. The user-defined template cannot be instantiated due to enable_if, yet the compiler still compiles by falling back to the intrinsic.

Actual Behavior The compiler calls the HLSL intrinsic (dot) instead of the user-defined function in the custom namespace, silently ignoring the intended function.

Przemog1 avatar Dec 04 '25 10:12 Przemog1

Important note, this affects DXIL codegen too https://godbolt.org/z/1zPxhbPWj