Files
TheRock/compiler/amd-llvm/clang/test/Analysis/clang-suppress/friends.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

363 lines
10 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
void clang_analyzer_warnIfReached();
// Systematic tests for [[clang::suppress]] on classes with friend declarations.
//
// Pruned matrix of valid combinations:
// Axis 1: fwd-decl at namespace scope (yes / no)
// Axis 2: body location (inline / out-of-line)
// Axis 3: template (yes / no)
//
// Each case has a suppressed variant (class has [[clang::suppress]])
// and an unsuppressed variant (class without it).
// Placeholder types for triggering instantiations.
// - Type{A,B} should match an unconstrained template type parameter.
// - Specialized should match some specialization pattern.
struct TypeA{};
struct TypeB{};
struct Specialized{};
// ============================================================================
// Group A: Non-template friend functions
// ============================================================================
// --- A1: no fwd-decl, inline body ---
struct [[clang::suppress]] A1_Suppressed {
friend void a1_suppressed(A1_Suppressed) {
clang_analyzer_warnIfReached(); // no-warning
}
};
struct A1_Unsuppressed {
friend void a1_unsuppressed(A1_Unsuppressed) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_A1() {
a1_suppressed(A1_Suppressed{});
a1_unsuppressed(A1_Unsuppressed{});
}
// --- A2: no fwd-decl, out-of-line body ---
struct [[clang::suppress]] A2_Suppressed {
friend void a2_suppressed(A2_Suppressed);
};
void a2_suppressed(A2_Suppressed) {
// Out-of-line: lexical parent is the translation unit, NOT the class.
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
struct A2_Unsuppressed {
friend void a2_unsuppressed(A2_Unsuppressed);
};
void a2_unsuppressed(A2_Unsuppressed) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_A2() {
a2_suppressed(A2_Suppressed{});
a2_unsuppressed(A2_Unsuppressed{});
}
// --- A3: fwd-decl, inline body ---
extern void a3_suppressed();
struct [[clang::suppress]] A3_Suppressed {
friend void a3_suppressed() {
clang_analyzer_warnIfReached(); // no-warning
}
};
extern void a3_unsuppressed();
struct A3_Unsuppressed {
friend void a3_unsuppressed() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_A3() {
a3_suppressed();
a3_unsuppressed();
}
// --- A4: fwd-decl, out-of-line body ---
extern void a4_suppressed();
struct [[clang::suppress]] A4_Suppressed {
friend void a4_suppressed();
};
void a4_suppressed() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
extern void a4_unsuppressed();
struct A4_Unsuppressed {
friend void a4_unsuppressed();
};
void a4_unsuppressed() {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_A4() {
a4_suppressed();
a4_unsuppressed();
}
// ============================================================================
// Group B: Friend function templates (primary template)
// ============================================================================
// --- B1: no fwd-decl, inline body ---
struct [[clang::suppress]] B1_Suppressed {
template <typename T>
friend void b1_suppressed(B1_Suppressed, T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
struct B1_Unsuppressed {
template <typename T>
friend void b1_unsuppressed(B1_Unsuppressed, T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_B1() {
b1_suppressed(B1_Suppressed{}, TypeA{});
b1_unsuppressed(B1_Unsuppressed{}, TypeA{});
}
// --- B2: no fwd-decl, out-of-line body ---
struct [[clang::suppress]] B2_Suppressed {
template <typename T>
friend void b2_suppressed(B2_Suppressed, T);
};
template <typename T>
void b2_suppressed(B2_Suppressed, T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
struct B2_Unsuppressed {
template <typename T>
friend void b2_unsuppressed(B2_Unsuppressed, T);
};
template <typename T>
void b2_unsuppressed(B2_Unsuppressed, T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_B2() {
b2_suppressed(B2_Suppressed{}, TypeA{});
b2_unsuppressed(B2_Unsuppressed{}, TypeA{});
}
// --- B3: fwd-decl, inline body ---
template <typename T>
extern void b3_suppressed(T);
struct [[clang::suppress]] B3_Suppressed {
template <typename T>
friend void b3_suppressed(T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <typename T>
extern void b3_unsuppressed(T);
struct B3_Unsuppressed {
template <typename T>
friend void b3_unsuppressed(T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_B3() {
b3_suppressed(TypeA{});
b3_unsuppressed(TypeA{});
}
// --- B4: fwd-decl, out-of-line body ---
template <typename T>
extern void b4_suppressed(T);
struct [[clang::suppress]] B4_Suppressed {
template <typename T>
friend void b4_suppressed(T);
};
template <typename T>
void b4_suppressed(T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
template <typename T>
extern void b4_unsuppressed(T);
struct B4_Unsuppressed {
template <typename T>
friend void b4_unsuppressed(T);
};
template <typename T>
void b4_unsuppressed(T) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_B4() {
b4_suppressed(TypeA{});
b4_unsuppressed(TypeA{});
}
// ============================================================================
// Group C: Friend function template explicit specializations
// ============================================================================
// --- C1: primary inline in suppressed class, explicit spec defined out-of-line ---
// The explicit specialization is NOT defined inside the class, so it should
// NOT be suppressed.
struct [[clang::suppress]] C1_Suppressed {
template <typename T>
friend void c1_suppressed(C1_Suppressed, T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
template <>
void c1_suppressed(C1_Suppressed, Specialized) {
// Explicit specialization defined outside the class — not suppressed.
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
void test_C1() {
c1_suppressed(C1_Suppressed{}, TypeA{}); // uses primary (suppressed)
c1_suppressed(C1_Suppressed{}, Specialized{}); // uses explicit spec (not suppressed)
}
// ============================================================================
// Group D: Friend classes (declared, not defined inline — C++ forbids
// defining a type in a friend declaration)
// ============================================================================
// --- D1: friend class only declared, defined outside ---
struct [[clang::suppress]] D1_Suppressed {
friend struct D1_FriendOuter;
};
struct D1_FriendOuter {
void method() {
// Defined outside the suppressed class — not suppressed.
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_D1() {
D1_FriendOuter{}.method();
}
// ============================================================================
// Group E: Edge cases
// ============================================================================
// --- E1: friend function in suppressed CLASS TEMPLATE (not just suppressed class) ---
template <typename U>
struct [[clang::suppress]] E1_SuppressedTmpl {
friend void e1_friend(E1_SuppressedTmpl) {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_E1() {
e1_friend(E1_SuppressedTmpl<TypeA>{});
}
// --- E2: friend function template in a nested suppressed class ---
// The friend needs a parameter of the nested class type for ADL lookup.
struct Outer_E2 {
struct [[clang::suppress]] Inner_E2 {
template <typename T>
friend void e2_inner_friend(Inner_E2, T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
};
void test_E2() {
e2_inner_friend(Outer_E2::Inner_E2{}, TypeA{});
}
// --- E3: multiple redeclarations at namespace scope before friend decl ---
template <typename T> void e3_multi_redecl(T);
template <typename T> void e3_multi_redecl(T);
template <typename T> void e3_multi_redecl(T);
struct [[clang::suppress]] E3_Suppressed {
template <typename T>
friend void e3_multi_redecl(T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_E3() {
e3_multi_redecl(TypeA{});
}
// --- E4: friend in anonymous namespace ---
namespace {
struct [[clang::suppress]] E4_AnonSuppressed {
friend void e4_anon_friend(E4_AnonSuppressed) {
clang_analyzer_warnIfReached(); // no-warning
}
};
} // namespace
void test_E4() {
e4_anon_friend(E4_AnonSuppressed{});
}
// --- E5: suppression on the friend declaration itself, not on the class ---
// Friend functions need a parameter for ADL visibility.
struct E5_ClassNotSuppressed {
[[clang::suppress]] friend void e5_suppressed(E5_ClassNotSuppressed) {
clang_analyzer_warnIfReached(); // no-warning
}
friend void e5_unsuppressed(E5_ClassNotSuppressed) {
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
}
};
void test_E5() {
e5_suppressed(E5_ClassNotSuppressed{});
e5_unsuppressed(E5_ClassNotSuppressed{});
}
// --- E6: friend function template in suppressed class template, with fwd-decl ---
// Combines class template + function template + fwd-decl.
template <typename T> void e6_combined(T);
template <typename U>
struct [[clang::suppress]] E6_SuppressedTmpl {
template <typename T>
friend void e6_combined(T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_E6() {
// Instantiate the class template to make the friend visible.
E6_SuppressedTmpl<TypeA> e6; // This line is IMPORTANT!
(void)e6;
e6_combined(TypeA{});
}
// --- E7: friend function template instantiated with multiple different types ---
// Ensure suppression applies to ALL instantiations, not just one.
struct [[clang::suppress]] E7_Suppressed {
template <typename T>
friend void e7_multi_inst(E7_Suppressed, T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_E7() {
e7_multi_inst(E7_Suppressed{}, TypeA{});
e7_multi_inst(E7_Suppressed{}, TypeB{});
}
// --- E8: friend function template with fwd-decl, instantiated with multiple types ---
template <typename T> void e8_fwd_multi(T);
struct [[clang::suppress]] E8_Suppressed {
template <typename T>
friend void e8_fwd_multi(T) {
clang_analyzer_warnIfReached(); // no-warning
}
};
void test_E8() {
e8_fwd_multi(TypeA{});
e8_fwd_multi(TypeB{});
}