Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CUDA Template Restrictions

CUDA's split-compilation model imposes restrictions on C++ templates that have no counterpart in standard C++. When a __global__ function template is instantiated, cudafe++ generates a host-side stub whose mangled name must exactly match what the device compiler (cicc) independently produces. This agreement is only possible if both compilers can derive the complete mangled name from the template's signature and arguments. Types that are invisible to one side -- host-local types, unnamed types, private class members, certain lambda closures -- break this invariant and are therefore rejected. The same constraints apply to variable templates used in device contexts, and additional structural restrictions prevent variadic __global__ templates from producing ambiguous mangled names. This page documents all 24 CUDA-specific template restriction errors across 8 categories, the implementation functions that enforce them, and the __NV_name_expr mechanism that relies on these guarantees.

Key Facts

PropertyValue
Source filecp_gen_be.c (EDG 6.6 backend code generator)
Access checkersub_469F80 (template_arg_is_accessible, 144 lines)
Cache enginesub_469480 (cache_access_result_for, 670 lines)
Arg list walkersub_46A230 (walks template arg lists, 182 lines)
Pre-unnamed checksub_46A5B0 (arg_before_unnamed_template_param_arg, 396 lines)
Scope resolversub_469F30 (resolves scope via hash lookup, 23 lines)
Callback for scope walksub_46ACC0 (passed as callback into sub_61FE60)
Cache hash tablexmmword_F05720 (384 KB, 16,382-entry table, 24 bytes per slot)
Entity lookup tableunk_FE5700 (512 KB, used by sub_469F30)
Free list headqword_F05708 (recycled cache entries)
Total restriction errors24 across 8 categories

Why These Restrictions Exist

The CUDA compilation model splits a single .cu source file into two compilation paths:

  1. Host path: cudafe++ generates a .int.c file containing host stubs. The host compiler (gcc, clang, MSVC) compiles these stubs and produces a host object file. Each __global__ function template instantiation becomes a __wrapper__device_stub_ function.

  2. Device path: The same source is compiled by cicc into PTX. The device compiler independently instantiates the same templates and produces the device-side function bodies.

At link time, the CUDA runtime matches host stubs to device functions by mangled name. Both compilers must produce identical mangled names for every __global__ template instantiation. This is only possible when all template arguments are types that both compilers can see, name, and mangle identically. A host-only local type, for example, exists only in the host compiler's scope -- cicc cannot see it and cannot produce a matching mangled name. The restrictions documented below enforce this invariant.

The same logic applies to __device__/__constant__ variable templates, which must also match across the host/device boundary for registration and symbol lookup.

Category A: __global__ Declaration Restrictions (8 errors)

These errors prevent __global__ function templates from using C++ features that would prevent host stub generation or violate kernel ABI constraints.

TagMessageReason
global_function_constexprA __global__ function or function template cannot be marked constexprKernels are not evaluated at compile time; constexpr is meaningless for device launch.
global_function_constevalA __global__ function or function template cannot be marked constevalconsteval requires compile-time evaluation, incompatible with runtime kernel launch.
global_class_declA __global__ function or function template cannot be a member functionKernels have no this pointer; the launch ABI has no slot for an object reference.
global_friend_definitionA __global__ function or function template cannot be defined in a friend declarationFriend definitions have limited visibility, conflicting with the requirement for a globally-linkable stub.
global_exception_specAn exception specification is not allowed for a __global__ function or function templateGPU hardware has no exception unwinding mechanism.
global_function_in_unnamed_inline_nsA __global__ function or function template cannot be declared within an inline unnamed namespaceUnnamed namespaces produce TU-local linkage, but kernel stubs must have external linkage for runtime registration.
global_function_with_initializer_lista __global__ function or function template cannot have a parameter with type std::initializer_liststd::initializer_list holds a pointer to backing storage that cannot be transparently transferred to device memory.
global_va_list_typeA __global__ function or function template cannot have a parameter with va_list typeVariadic argument lists require stack-based access that does not exist on GPU hardware.

These checks occur during attribute application in apply_nv_global_attr (sub_40E1F0 / sub_40E7F0) and in the post-validation pass nv_validate_cuda_attributes (sub_6BC890). The checks apply equally to non-template __global__ functions and __global__ function templates.

Category B: Variadic __global__ Template Constraints (2 errors)

Standard C++ allows multiple parameter packs in a template and does not require packs to be the last parameter. CUDA restricts this for __global__ templates because the host stub ABI requires unambiguous argument layout.

TagMessage
global_function_pack_not_lastPack template parameter must be the last template parameter for a variadic __global__ function template
global_function_multiple_packsMultiple pack parameters are not allowed for a variadic __global__ function template

Rationale

The kernel launch wrapper (<<<grid, block>>>) must marshal each argument into a contiguous parameter buffer. For a variadic template like template<typename... Ts> __global__ void kernel(Ts... args), the compiler generates the buffer layout at instantiation time. If the pack is not last, or if multiple packs are present, the positional mapping between template parameters and launch arguments becomes ambiguous -- the compiler cannot determine which arguments belong to which pack without full deduction context that may not be available at stub generation time.

Example

// OK: single pack, last position
template<typename T, typename... Ts>
__global__ void kernel(T first, Ts... rest);

// Error: pack not last
template<typename... Ts, typename T>
__global__ void kernel(Ts... args, T last);  // global_function_pack_not_last

// Error: multiple packs
template<typename... Ts, typename... Us>
__global__ void kernel(Ts... a, Us... b);    // global_function_multiple_packs

Category C: Template Argument Visibility for __global__ (6 errors)

These are the core name-mangling restrictions. Every type used as a template argument to a __global__ function template instantiation must be visible and nameable by both the host and device compilers.

C.1: Host-local types

TagMessage
global_func_local_template_argA type defined inside a __host__ function (%t) cannot be used in the template argument type of a __global__ function template instantiation

A type defined inside a __host__ function exists only within that function's scope. The device compiler never sees it and cannot produce a matching mangled name.

void host_function() {
    struct LocalType { int x; };
    kernel<LocalType><<<1,1>>>();  // error: host-local type
}

C.2: Private/protected class members

TagMessage
global_private_type_argA type that is defined inside a class and has private or protected access (%t) cannot be used in the template argument type of a __global__ function template instantiation, unless the class is local to a __device__ or __global__ function

Private/protected nested types are accessible only through the enclosing class's access control. While C++ allows friend access and member function access to these types, the device compiler processes templates independently and may not have the same access context. The exception for types local to __device__/__global__ functions reflects that both compilers see device function bodies.

class Outer {
    struct Inner { int x; };     // private
    friend void launch();
};

void launch() {
    kernel<Outer::Inner><<<1,1>>>();  // error: private type
}

C.3: Unnamed types

TagMessage
global_unnamed_type_argAn unnamed type (%t) cannot be used in the template argument type of a __global__ function template instantiation, unless the type is local to a __device__ or __global__ function

Unnamed types (anonymous structs, unnamed enums) have no canonical name. Itanium ABI mangling for unnamed types relies on positional encoding within the enclosing scope, which may differ between host and device compilers if they process the enclosing scope differently. Types local to __device__/__global__ functions are exempt because the device compiler processes those scopes identically.

enum { A, B, C };                     // unnamed enum
kernel<decltype(A)><<<1,1>>>();       // error: unnamed type

C.4: Lambda closures

TagMessage
global_lambda_template_argThe closure type for a lambda (%t%s) cannot be used in the template argument type of a __global__ function template instantiation, unless the lambda is defined within a __device__ or __global__ function, or the flag '-extended-lambda' is specified and the lambda is an extended lambda (a __device__ or __host__ __device__ lambda defined within a __host__ or __host__ __device__ function)

Lambda closures are compiler-generated anonymous types. Without --extended-lambda, there is no protocol for both compilers to agree on the closure type's mangled representation. The extended lambda mechanism (--extended-lambda / --extended-lambda) establishes a naming convention for lambdas annotated with __device__ or __host__ __device__, enabling cross-compiler name agreement.

auto f = [](int x){ return x*2; };
kernel<decltype(f)><<<1,1>>>();       // error unless extended lambda

C.5: Private/protected template template arguments

TagMessage
global_private_template_argA template that is defined inside a class and has private or protected access cannot be used in the template template argument of a __global__ function template instantiation

The same access-control problem as C.2, but for template template parameters. A private class template used as a template template argument cannot be guaranteed visible in the device compiler's independent instantiation context.

C.6: Texture/surface non-type arguments

Message
A texture or surface variable cannot be used in the non-type template argument of a __device__, __host__ __device__ or __global__ function template instantiation

Texture and surface objects have special hardware semantics. Their runtime addresses are not fixed at compile time (they are bound through the texture subsystem), so they cannot serve as non-type template arguments whose values must be known to produce a deterministic mangled name.

Implementation: The Access Checking Pipeline

The template argument restriction checks are implemented in a three-function pipeline within cp_gen_be.c:

sub_469F80 — template_arg_is_accessible

This is the primary entry point. It dispatches on the template argument kind (byte at arg+8):

int template_arg_is_accessible(arg_t *a1, int scope_depth, char check_scope, int *cache_miss) {
    arg->flags_25 |= 0x10;               // mark: currently checking
    int kind = arg->kind;                 // offset +8
    
    switch (kind) {
    case 0:  // type argument
        type = arg->value;               // offset +32
        result = cache_access_result_for(type, 6, scope_depth, cache_miss);
        if (!result && (check_scope & 1)) {
            // walk through typedef chains (type_kind == 12)
            while (type->kind == 12)
                type = type->canonical;   // offset +144
            result = cache_access_result_for(type, 6, scope_depth, cache_miss);
            if (!result) {
                sub_469F30(&type_holder, 0);   // resolve via entity lookup
                result = (type_holder != original_type);
            }
        }
        break;
        
    case 1:  // template argument (template template parameter)
        entity = arg->value;             // offset +32
        // Check class accessibility via derivation chain
        if (entity->base_class) {        // offset +128
            // Use IL walker sub_61FE60 with callback sub_46ACC0
            sub_61EC40(visitor_state);
            visitor_state[0] = sub_46ACC0;   // the callback
            sub_61FE60(entity->base_class, visitor_state);
            result = (visitor_state->found == 0);
        }
        break;
        
    case 2:  // non-type argument
        result = cache_access_result_for(arg->value, 58, scope_depth, cache_miss);
        break;
        
    default:
        __assert_fail("template_arg_is_accessible", "cp_gen_be.c", 2448);
    }
    
    arg->flags_25 &= ~0x10;              // clear: done checking
    return result;
}

The flags_25 |= 0x10 / &= ~0x10 pattern is a recursion guard: it marks the argument as "currently being checked" to prevent infinite loops through mutually-referential template arguments.

sub_469480 — cache_access_result_for

This function caches the result of access checking for a given entity to avoid redundant computation. The cache is a hash table at xmmword_F05720 with 16,382 buckets (0x3FFF), each 24 bytes wide.

Cache entry layout (24 bytes):

OffsetSizeFieldDescription
+08nextPointer to next entry in chain (collision list)
+88entityEntity pointer being cached
+164scope_idScope identifier from qword_1065708 chain
+201resultCached access result (1 = accessible, 0 = not)
+211arg_kindTemplate argument kind that was checked

Hash function: The entity pointer is right-shifted by 6 bits, then taken modulo 0x3FFF:

unsigned hash = ((unsigned)(entity >> 6) * 262161ULL) >> 32;
unsigned bucket = (entity >> 6)
    - 0x3FFF * (((hash + ((entity >> 6) - hash) >> 1)) >> 13);
char *slot = &xmmword_F05720[24 * bucket];

Cache hit path: If slot->entity == entity and the scope matches, return the cached result immediately. The function walks the qword_1065708 chain (the scope stack) to verify that the cached result was computed in a compatible scope context.

Cache eviction: When a cached entry's scope no longer matches (the scope stack has changed since caching), the entry is moved to the free list (qword_F05708). New entries are allocated from the free list or via sub_6B7340 (24-byte allocation).

Fallback (cache miss): On cache miss, the function performs the actual accessibility analysis:

  1. For type arguments (kind 6): resolves typedefs, checks if the type is a class/struct/enum with access restrictions. Uses sub_5F9C10 to resolve through elaborated type specifiers. Checks entity->access_bits at +80 (bits 0-1: 0=public, 1=protected, 2=private).

  2. For non-type arguments (kind 58): checks the entity's accessibility directly.

  3. For class/struct types (kinds 9-11): walks the class's template argument list recursively via sub_469F80.

  4. For dependent types (kind 14): recursively checks the base type.

  5. For function types (kind 7) and pointer-to-member types (kind 13): recursively checks the return type, parameter types, and pointed-to class.

After computing the result, it is stored in the cache for future lookups.

sub_46A230 — Template Arg List Walker

This function walks a template instantiation's argument list and checks each argument for accessibility. It uses the entity lookup hash table at unk_FE5700 to find cached resolution results.

__int64 walk_template_args(__int64 hash_table, unsigned __int64 type) {
    // Resolve through typedef chains
    while (type->kind == 12)
        type = type->canonical;           // offset +144
    
    // Hash the type pointer into a bucket
    _QWORD *bucket = hash_table + 32 * ((type >> 6) % 0x3FFF);
    
    // Walk the bucket chain
    while (bucket && bucket[1]) {
        entry = bucket[1];                // the entity entry
        
        // Check if this entry matches our type
        if (entry->canonical != type && !sub_7B2260(entry->canonical, type, 0))
            continue;
        
        // Scope compatibility check
        if (bucket[2] && bucket[2] != qword_126C5D0)
            continue;
        
        // For template entities (kind 10), walk their argument lists
        if (entry->kind == 10) {
            arg_list = *entry->template_args;
            while (arg) {
                if (arg->flags_25 & 0x10)     // already being checked
                    goto next;
                if (!template_arg_is_accessible(arg, 0, 0, &miss))
                    goto not_found;
                arg = arg->next;
            }
        }
        
        // Access check on the entity itself
        if (entry->access_bits != 0)      // private/protected
            if (!sub_467780(entity, 1, 0)) // check access
                goto not_found;
        
        // Cache the resolved entity in bucket[3]
        bucket[3] = qword_10657E8;
        return entry;
    }
    return 0;
}

The walker handles three argument kinds:

  • Kind 0 (type): Checks the type entity's accessibility and, for class templates (kind 12 with subkind 10), recursively walks nested template arguments.
  • Kind 1 (template): Checks the template entity's class ancestry.
  • Kind 2 (non-type): Resolves the non-type argument's scope via sub_5F9BC0.

sub_46A5B0 — arg_before_unnamed_template_param_arg

This function handles the generation of template arguments that appear before unnamed template parameter arguments. It determines the positional index of each argument relative to the template parameter list and calls the appropriate code-generation routine. The assert at line 4795 guards against an unexpected argument kind (must be 0, 1, or 2; kind 3 is a pack expansion sentinel).

Category D: Variable Template Parallel Restrictions (5 errors)

Variable templates (template<typename T> __device__ T var = ...) used in device contexts carry the same restrictions as __global__ function templates. The diagnostics mirror Category C exactly:

TagMessage
variable_template_private_type_argA type that is defined inside a class and has private or protected access (%t) cannot be used in the template argument type of a variable template instantiation, unless the class is local to a __device__ or __global__ function
variable_template_private_template_arg(private template template arg in variable template)
variable_template_unnamed_type_template_argAn unnamed type (%t) cannot be used in the template argument type of a variable template template instantiation, unless the type is local to a __device__ or __global__ function
variable_template_func_local_template_argA type defined inside a __host__ function (%t) cannot be used in the template argument type of a variable template template instantiation
variable_template_lambda_template_argThe closure type for a lambda (%t%s) cannot be used in the template argument type of a variable template instantiation, unless the lambda is defined within a __device__ or __global__ function, or the lambda is an 'extended lambda' and the flag --extended-lambda is specified

The implementation shares the same cache_access_result_for / template_arg_is_accessible pipeline described in the Category C implementation section. The only difference is the error tag and message string emitted on failure.

Why Variable Templates Need the Same Restrictions

Variable templates instantiated with __device__, __constant__, or __managed__ memory space are registered by the CUDA runtime using their mangled names. The host-side .int.c file contains registration arrays (emitted in .nvHRDE, .nvHRDI, .nvHRCE, .nvHRCI sections) whose entries are byte arrays encoding mangled variable names. The device compiler independently mangles the same variable template instantiation. Both must produce identical names, so the same visibility constraints apply.

Category E: Static Global Template Stub (2 errors)

In whole-program compilation mode (-rdc=false) with -static-global-template-stub=true, template __global__ functions receive static linkage on their host stubs. This prevents ODR violations when the same template kernel is instantiated in multiple translation units. Two scenarios are incompatible with this mode:

TagMessage
extern_kernel_templatewhen "-static-global-template-stub=true", extern __global__ function template is not supported in whole program compilation mode ("-rdc=false"). To resolve the issue, either use separate compilation mode ("-rdc=true"), or explicitly set "-static-global-template-stub=false" (but see nvcc documentation about downsides of turning it off)
template_global_no_defwhen "-static-global-template-stub=true" in whole program compilation mode ("-rdc=false"), a __global__ function template instantiation or specialization (%sq) must have a definition in the current translation unit. To resolve this issue, either use separate compilation mode ("-rdc=true"), or explicitly set "-static-global-template-stub=false" (but see nvcc documentation about downsides of turning it off)

The Problem

An extern template kernel declaration says "this template instantiation exists elsewhere." But if the stub is static, there is no way for the linker to resolve the extern reference to a stub in another TU, because static symbols are TU-local. Similarly, a template instantiation without a definition in the current TU cannot have a static stub generated for it, because there is no body to inline.

Resolution Paths

Both diagnostics suggest the same two alternatives:

  1. Switch to -rdc=true (separate compilation): each TU gets its own device object, and cross-TU kernel references are resolved by the device linker (nvlink).
  2. Set -static-global-template-stub=false: stubs get external linkage, allowing cross-TU references at the cost of potential ODR violations if the same template is instantiated in multiple TUs.

Category F: Local Type Prevents Host Launch (1 error)

TagMessage
local_type_used_in_global_functiona local type %t (defined in %sq1) used in global function %sq2 template argument, the global function cannot be launched from host code.

This is a warning-level diagnostic, not a hard error. It fires when a type local to a function (but not a __host__-function-local type, which would be Category C.1) is used as a template argument. The kernel can still be instantiated and called from device code, but the host-side launch path is blocked because the local type is not visible to the host stub generator.

This diagnostic differs from global_func_local_template_arg in severity and scope: it is a soft warning that the kernel "cannot be launched from host code," rather than a hard error that rejects the instantiation entirely.

Category G: __grid_constant__ in Instantiation Directives (1 error)

TagMessage
grid_constant_incompat_templ_redeclincompatible __grid_constant__ annotation for parameter %s in function template redeclaration (see previous declaration %p)

When a function template is redeclared, the __grid_constant__ annotations on its parameters must match the original declaration. This is enforced because __grid_constant__ affects the ABI: a parameter marked __grid_constant__ is placed in constant memory and accessed through a different addressing mode. If a redeclaration omits the annotation, the host stub and device function would disagree on parameter layout.

The related diagnostic grid_constant_incompat_instantiation_directive applies to explicit instantiation directives (template __global__ void kernel<int>(...)) and is documented in the grid_constant page.

Category H: Kernel Launches from System File Templates (1 error)

Message
kernel launches from templates are not allowed in system files

This error fires when a <<<...>>> kernel launch expression appears inside a template function defined in a system header file. System headers are files marked with #pragma system_header or located in system include paths (e.g., the CUDA toolkit's include/ directory).

The restriction exists because system headers are processed with relaxed diagnostics. Kernel launch expressions inside template functions in system headers would be instantiated in user code contexts, but the launch transformation (replacing <<<...>>> with cudaConfigureCall + stub call) operates during the system header's processing pass where diagnostic state may be suppressed. Rather than risk silent miscompilation, the compiler rejects this pattern outright.

The __NV_name_expr Mechanism (6 errors)

NVRTC (NVIDIA's runtime compilation library) provides a mechanism to obtain the mangled name of a __global__ function or __device__/__constant__ variable at compile time. This mechanism is exposed through the __CUDACC_RTC__name_expr intrinsic, which the frontend processes during lowered name lookup.

Purpose

NVRTC compiles CUDA code at runtime, producing PTX that is loaded into the driver. The host application needs to look up compiled kernels and device variables by name via cuModuleGetFunction / cuModuleGetGlobal. The __NV_name_expr mechanism bridges this gap: the user provides a C++ name expression (e.g., my_kernel<int> or my_device_var<float>), and the compiler returns the corresponding mangled name (e.g., _Z9my_kernelIiEvv).

The 6 Errors

TagMessage
name_expr_parsingError in parsing name expression for lowered name lookup. Input name expression was: %sq
name_expr_extra_tokensExtra tokens found after parsing name expression for lowered name lookup. Input name expression was: %sq
name_expr_internal_errorInternal error in parsing name expression for lowered name lookup. Input name expression was: %sq
name_expr_non_global_routineName expression cannot form address of a non-__global__ function. Input name expression was: %sq
name_expr_non_device_variableName expression cannot form address of a variable that is not a __device__/__constant__ variable. Input name expression was: %sq
name_expr_not_routine_or_variableName expression must form address of a __global__ function or the address of a __device__/__constant__ variable. Input name expression was: %sq

Processing Pipeline

  1. Parsing: The name expression is parsed as a C++ id-expression. If parsing fails, name_expr_parsing is emitted. If tokens remain after a successful parse, name_expr_extra_tokens fires.

  2. Lookup: The parsed expression is resolved via standard C++ name lookup (qualified or unqualified, with template argument deduction if needed).

  3. Validation: The resolved entity is checked:

    • If it is a function, it must be __global__ (has the __global__ execution space byte set). Otherwise: name_expr_non_global_routine.
    • If it is a variable, it must be __device__ or __constant__ (memory space bits at entity+148). Otherwise: name_expr_non_device_variable.
    • If it is neither a function nor a variable: name_expr_not_routine_or_variable.
  4. Mangling: If validation passes, the entity is mangled using the Itanium ABI mangler (in lower_name.c) and the resulting string is recorded for NVRTC output.

Connection to Template Restrictions

The __NV_name_expr mechanism relies on every template argument being mangeable. All of the Category C restrictions directly support this: if a template argument type cannot be mangled (because it is unnamed, local, private, etc.), the name expression lookup would produce a mangled name that does not match the device-side mangling. The restrictions are enforced at template instantiation time, before any name expression lookup occurs, so that invalid instantiations never reach the mangling stage.

Data Structures

Template Argument Node (arg_t)

The template argument node is a linked-list entry used by sub_469F80 and sub_46A230:

OffsetSizeFieldDescription
+08nextNext argument in the list
+81kindArgument kind: 0=type, 1=template, 2=non-type, 3=pack expansion
+241flags_24Bit 0: is pack expansion
+251flags_25Bit 4 (0x10): currently being checked (recursion guard)
+328valuePointer to the type/entity/expression

Entity Node (type/symbol)

Relevant fields for accessibility checking:

OffsetSizeFieldDescription
+88name_entryName string pointer (or next scope for unnamed)
+248alt_nameAlternative name (for flag bit 3 at +81)
+408scope_infoScope information; +32 from this is the enclosing class/namespace
+801access_bitsBits 0-1: access specifier (0=public, 1=protected, 2=private)
+811entity_flagsBit 2 (0x04): is template specialization; bit 6 (0x40): is anonymous
+1288base_classBase class pointer (for class entities)
+1321type_kindType kind: 6/8=pointer/ref, 7=function, 9-11=class/struct/enum, 12=typedef, 13=pointer-to-member, 14=dependent
+1448canonicalCanonical type (for typedefs: the underlying type)
+1481subtype_kindSubkind (for type_kind 12: 10=template-id, 12=elaborated)
+1528type_infoType-specific data (template args, function params, etc.)
+1601template_kindFor template entities: template kind
+1611visibilityBit 7 (0x80): private visibility (negative char value)
+1622extra_flagsBit 7 (0x80) + bit 9 (0x200): cached accessibility state

Diagnostic Summary

All 24 errors sorted by category:

#CategoryTagSeverity
1Aglobal_function_constexprerror
2Aglobal_function_constevalerror
3Aglobal_class_declerror
4Aglobal_friend_definitionerror
5Aglobal_exception_specerror
6Aglobal_function_in_unnamed_inline_nserror
7Aglobal_function_with_initializer_listerror
8Aglobal_va_list_typeerror
9Bglobal_function_pack_not_lasterror
10Bglobal_function_multiple_packserror
11Cglobal_func_local_template_argerror
12Cglobal_private_type_argerror
13Cglobal_unnamed_type_argerror
14Cglobal_lambda_template_argerror
15Cglobal_private_template_argerror
16C(texture/surface non-type arg)error
17Dvariable_template_private_type_argerror
18Dvariable_template_private_template_argerror
19Dvariable_template_unnamed_type_template_argerror
20Dvariable_template_func_local_template_argerror
21Dvariable_template_lambda_template_argerror
22Eextern_kernel_templateerror
23Etemplate_global_no_deferror
24Flocal_type_used_in_global_functionwarning

Category G (grid_constant_incompat_templ_redecl) and Category H (kernel launches from templates...) are counted separately as they span the template/non-template boundary.

Function Map

AddressIdentityLinesRole
sub_469F80template_arg_is_accessible144Primary access checker -- dispatches on arg kind
sub_469480cache_access_result_for670Hash-cached accessibility analysis
sub_46A230(walks template arg lists)182Iterates entity lookup table for arg lists
sub_46A5B0arg_before_unnamed_template_param_arg396Handles args before unnamed template params
sub_469F30(scope resolve helper)23Resolves scope via cache_access_result_for + entity lookup
sub_46ACC0(scope walk callback)--Callback passed to IL walker sub_61FE60
sub_467780(access check)--Checks C++ access control (public/protected/private)
sub_466F40(output callback)--Code generation output callback
sub_5BFC70(pack expansion resolver)--Resolves pack expansion nodes (kind 3)
sub_5F9BC0(scope resolver)--Resolves entity scope chain
sub_5F9C10(elaborated type resolver)--Resolves elaborated type specifiers
sub_7B2260(type equivalence)--Checks structural type equivalence
sub_61EC40(init visitor)27Initializes IL tree visitor state
sub_61FE60(walk expression tree)17Walks expression tree with callback

Global Variables

GlobalAddressDescription
xmmword_F057200xF05720Access check cache hash table (384 KB, 16,382 entries x 24 bytes)
qword_F057080xF05708Free list head for recycled cache entries
qword_F057300xF05730Scope ID array parallel to cache (4 bytes per entry)
unk_FE57000xFE5700Entity lookup hash table (512 KB)
qword_10657080x1065708Scope stack head (linked list of scope entries)
qword_126C5D00x126C5D0Global scope sentinel
qword_10657E80x10657E8Current scope context for entity resolution
dword_10658480x1065848Extended lambda mode flag
dword_10658500x1065850Device stub mode flag

Cross-References