// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s void clang_analyzer_warnIfReached(); // Systematic tests for [[clang::suppress]] on template methods inside // non-template and template classes. // Placeholder types for triggering instantiations. // - Type{A,B} should match an unconstrained template type parameter. struct TypeA{}; struct TypeB{}; // ============================================================================ // Group A: Non-template class with suppressed/unsuppressed template methods // ============================================================================ struct NonTemplateClassWithTemplatedMethod { template [[clang::suppress]] void suppressed(T) { clang_analyzer_warnIfReached(); // no-warning } template void unsuppressed(T) { clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} } }; void test_nontpl_class() { NonTemplateClassWithTemplatedMethod().suppressed(TypeA{}); NonTemplateClassWithTemplatedMethod().unsuppressed(TypeA{}); } // ============================================================================ // Group B: Template class with template methods — inline // ============================================================================ template struct TemplateClassWithTemplateInlineMethod { template [[clang::suppress]] void suppressed(U) { clang_analyzer_warnIfReached(); // no-warning } template void unsuppressed(U) { clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} } }; void test_tpl_class_tpl_inline_method() { TemplateClassWithTemplateInlineMethod().suppressed(TypeB{}); TemplateClassWithTemplateInlineMethod().unsuppressed(TypeB{}); } // ============================================================================ // Group C: Template class with template methods — out-of-line // ============================================================================ template struct TemplateClassWithTemplateOOLMethod { template [[clang::suppress]] void suppress_at_decl_outline(U); template void suppress_at_def_outline(U); }; // Attribute on declaration only — NOT honored at out-of-line definition. template template void TemplateClassWithTemplateOOLMethod::suppress_at_decl_outline(U) { clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} } // Attribute on out-of-line definition — suppressed. template template [[clang::suppress]] void TemplateClassWithTemplateOOLMethod::suppress_at_def_outline(U) { clang_analyzer_warnIfReached(); // no-warning } void test_tpl_class_tpl_ool_method() { TemplateClassWithTemplateOOLMethod().suppress_at_decl_outline(TypeB{}); TemplateClassWithTemplateOOLMethod().suppress_at_def_outline(TypeB{}); } // ============================================================================ // Group D: Template-template parameters // ============================================================================ // A simple "box" template used as a template-template argument. template struct Box { void get() { clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} } }; // A version of Box that suppresses its own methods. template class [[clang::suppress]] SuppressedBox { public: void get() { clang_analyzer_warnIfReached(); // no-warning } }; // Adaptor whose own methods are suppressed; the contained Box's methods are not. template class Container> class [[clang::suppress]] SuppressedAdaptor { public: Container data; void adaptor_method() { clang_analyzer_warnIfReached(); // no-warning } }; // Adaptor with no suppression; Box's own suppression is independent. template class Container> struct UnsuppressedAdaptor { Container data; void adaptor_method() { clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} } }; void test_template_template() { // SuppressedAdaptor: adaptor method suppressed; Box::get not affected. SuppressedAdaptor().adaptor_method(); // suppressed by adaptor's attr SuppressedAdaptor().data.get(); // warns — Box has no attr, different lexical context // UnsuppressedAdaptor: adaptor warns; SuppressedBox::get suppressed. UnsuppressedAdaptor().adaptor_method(); // warns — adaptor has no attr UnsuppressedAdaptor().data.get(); // suppressed by SuppressedBox's attr }