Files
TheRock/compiler/amd-llvm/clang/test/Analysis/clang-suppress/class-template-specializations.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

349 lines
9.4 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
void clang_analyzer_warnIfReached();
// ============================================================================
// Group A: Basic class template — attribute on primary
// ============================================================================
// Placeholder types for triggering instantiations.
// - Type{A,B} should match an unconstrained template type parameter.
// - Specialized{A,B} should match some specialization pattern.
struct TypeA{};
struct TypeB{};
struct SpecializedA{};
struct SpecializedB{};
template <typename T>
class [[clang::suppress]] A_Primary {
public:
void inline_method() {
clang_analyzer_warnIfReached(); // no-warning
}
void outline_method();
static void static_inline() {
clang_analyzer_warnIfReached(); // no-warning
}
static void static_outline();
};
template <typename T>
void A_Primary<T>::outline_method() {
// Out-of-line: lexical context is the translation unit.
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
template <typename T>
void A_Primary<T>::static_outline() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_A() {
A_Primary<TypeA>().inline_method();
A_Primary<TypeA>().outline_method();
A_Primary<TypeA>::static_inline();
A_Primary<TypeA>::static_outline();
// Different instantiation.
A_Primary<TypeB>().inline_method();
}
// ============================================================================
// Group B: Explicit full specialization — attribute isolation
// ============================================================================
// --- B1: attribute on primary only ---
template <typename T>
class [[clang::suppress]] B1_AttrOnPrimary {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
// Explicit specialization is independent — NOT suppressed.
template <>
struct B1_AttrOnPrimary<SpecializedA> {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_B1() {
B1_AttrOnPrimary<TypeA>().method(); // suppressed (primary)
B1_AttrOnPrimary<SpecializedA>().method(); // warns (spec, no attr)
}
// --- B2: attribute on specialization only ---
template <typename T>
struct B2_AttrOnSpec {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
template <>
class [[clang::suppress]] B2_AttrOnSpec<SpecializedA> {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_B2() {
B2_AttrOnSpec<TypeA>().method(); // warns (primary, no attr)
B2_AttrOnSpec<SpecializedA>().method(); // suppressed (spec has attr)
}
// --- B3: attribute on both primary and specialization ---
template <typename T>
class [[clang::suppress]] B3_AttrOnBoth {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <>
class [[clang::suppress]] B3_AttrOnBoth<SpecializedA> {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_B3() {
B3_AttrOnBoth<TypeA>().method(); // suppressed
B3_AttrOnBoth<SpecializedA>().method(); // suppressed
}
// ============================================================================
// Group C: Partial specializations
// ============================================================================
// --- C1: attribute on partial specialization only ---
template <typename T, typename U>
struct C1_AttrOnPartial {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
template <typename T>
class [[clang::suppress]] C1_AttrOnPartial<T, SpecializedA> {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_C1() {
C1_AttrOnPartial<TypeA, TypeA>().method(); // warns (primary, no attr)
C1_AttrOnPartial<TypeA, SpecializedA>().method(); // suppressed (partial spec)
}
// --- C2: attribute on primary, partial spec has none ---
template <typename T, typename U>
class [[clang::suppress]] C2_AttrOnPrimary {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <typename T>
struct C2_AttrOnPrimary<T, SpecializedA> {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_C2() {
C2_AttrOnPrimary<TypeA, TypeA>().method(); // suppressed (primary)
C2_AttrOnPrimary<TypeA, SpecializedA>().method(); // warns (partial spec, no attr)
}
// --- C3: two partial specializations, only one suppressed ---
template <typename T, typename U>
struct C3_TwoPartials {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
template <typename T>
class [[clang::suppress]] C3_TwoPartials<T, SpecializedA> {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <typename T>
struct C3_TwoPartials<T, SpecializedB> {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_C3() {
C3_TwoPartials<TypeA, TypeA>().method(); // warns (primary)
C3_TwoPartials<TypeA, SpecializedA>().method(); // suppressed (first partial)
C3_TwoPartials<TypeA, SpecializedB>().method(); // warns (second partial, no attr)
}
// ============================================================================
// Group D: Forward-declared class template (chooseDefinitionRedecl path)
// ============================================================================
// The template is forward-declared, then defined. chooseDefinitionRedecl()
// must find the definition among the redeclarations.
// --- D1: Forward-declared without attribute, defined with attribute ---
template <typename T>
class D1_ForwardDeclared;
template <typename T>
class [[clang::suppress]] D1_ForwardDeclared {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_D1() {
D1_ForwardDeclared<TypeA>().method();
}
// --- D2: Forward-declared without attribute, defined without attribute ---
template <typename T>
struct D2_ForwardDeclared_NoAttr;
template <typename T>
struct D2_ForwardDeclared_NoAttr {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_D2() {
D2_ForwardDeclared_NoAttr<TypeA>().method();
}
// ============================================================================
// Group E: Specialization with out-of-line (OOL) methods
// ============================================================================
template <typename T>
class [[clang::suppress]] E_SpecWithOOL {
public:
void inline_method() {
clang_analyzer_warnIfReached(); // no-warning
}
void outline_method();
};
template <typename T>
void E_SpecWithOOL<T>::outline_method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
// Explicit specialization with attribute and out-of-line method.
template <>
class [[clang::suppress]] E_SpecWithOOL<SpecializedA> {
public:
void inline_method() {
clang_analyzer_warnIfReached(); // no-warning
}
void outline_method();
};
// Out-of-line for the specialization — not suppressed.
void E_SpecWithOOL<SpecializedA>::outline_method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_E() {
E_SpecWithOOL<TypeA>().inline_method();
E_SpecWithOOL<TypeA>().outline_method();
E_SpecWithOOL<SpecializedA>().inline_method();
E_SpecWithOOL<SpecializedA>().outline_method();
}
// ============================================================================
// Group F: Nested class inside class template specialization
// ============================================================================
template <typename T>
class [[clang::suppress]] F_Outer {
public:
struct Inner {
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
};
template <typename T>
struct F_Outer_NoAttr {
struct Inner {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
};
void test_F() {
F_Outer<TypeA>::Inner().method();
F_Outer_NoAttr<TypeA>::Inner().method();
}
// ============================================================================
// Group G: Class template with default template arguments
// ============================================================================
template <typename T, typename U = TypeA>
class [[clang::suppress]] G_WithDefault {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <typename T, typename U = TypeA>
struct G_WithDefault_NoAttr {
void method() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_G() {
G_WithDefault<TypeA>().method(); // uses default U=TypeA
G_WithDefault<TypeA, TypeB>().method(); // explicit U=TypeB
G_WithDefault_NoAttr<TypeA>().method(); // uses default U=TypeA
}
// ============================================================================
// Group H: Explicit instantiation directive
// ============================================================================
template <typename T>
class [[clang::suppress]] H_ExplicitInst {
public:
void method() {
clang_analyzer_warnIfReached(); // no-warning
}
};
// Explicit instantiation.
template class H_ExplicitInst<SpecializedA>;
void test_H() {
H_ExplicitInst<SpecializedA>().method();
}