================
@@ -0,0 +1,151 @@
+// RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.MemoryUnsafeCastChecker -verify %s
+
+class Base { };
+class Derived : public Base { };
+
+void test_pointers(Base *base) {
+  Derived *derived_static = static_cast<Derived*>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *'}}
+  Derived *derived_reinterpret = reinterpret_cast<Derived*>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *'}}
+  Derived *derived_c = (Derived*)base;
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *'}}
+}
+
+void test_refs(Base &base) {
+  Derived &derived_static = static_cast<Derived&>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &'}}
+  Derived &derived_reinterpret = reinterpret_cast<Derived&>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &'}}
+  Derived &derived_c = (Derived&)base;
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &'}}
+}
+
+class BaseVirtual {
+  virtual void virtual_base_function();
+};
+
+class DerivedVirtual : public BaseVirtual {
+  void virtual_base_function() override { }
+};
+
+void test_dynamic_casts(BaseVirtual *base_ptr, BaseVirtual &base_ref) {
+  DerivedVirtual *derived_dynamic_ptr = 
dynamic_cast<DerivedVirtual*>(base_ptr);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BaseVirtual *' to 
derived type 'DerivedVirtual *'}}
+  DerivedVirtual &derived_dynamic_ref = 
dynamic_cast<DerivedVirtual&>(base_ref);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BaseVirtual' to 
derived type 'DerivedVirtual &'}}
+}
+
+struct BaseStruct { };
+struct DerivedStruct : BaseStruct { };
+
+void test_struct_pointers(struct BaseStruct *base_struct) {
+  struct DerivedStruct *derived_static = static_cast<struct 
DerivedStruct*>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct BaseStruct 
*' to derived type 'struct DerivedStruct *'}}
+  struct DerivedStruct *derived_reinterpret = reinterpret_cast<struct 
DerivedStruct*>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct BaseStruct 
*' to derived type 'struct DerivedStruct *'}}
+  struct DerivedStruct *derived_c = (struct DerivedStruct*)base_struct;
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct BaseStruct 
*' to derived type 'struct DerivedStruct *'}}
+}
+
+typedef struct BaseStruct BStruct;
+typedef struct DerivedStruct DStruct;
+
+void test_struct_refs(BStruct &base_struct) {
+  DStruct &derived_static = static_cast<DStruct&>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStruct' to 
derived type 'DStruct &'}}
+  DStruct &derived_reinterpret = reinterpret_cast<DStruct&>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStruct' to 
derived type 'DStruct &'}}
+  DStruct &derived_c = (DStruct&)base_struct;
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStruct' to 
derived type 'DStruct &'}}
+}
+
+int counter = 0;
+void test_recursive(BStruct &base_struct) {
+  if (counter == 5)
+    return;
+  counter++;
+  DStruct &derived_static = static_cast<DStruct&>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStruct' to 
derived type 'DStruct &'}}
+}
+
+template<typename T>
+class BaseTemplate { };
+
+template<typename T>
+class DerivedTemplate : public BaseTemplate<T> { };
+
+void test_templates(BaseTemplate<int> *base, BaseTemplate<int> &base_ref) {
+  DerivedTemplate<int> *derived_static = 
static_cast<DerivedTemplate<int>*>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BaseTemplate<int> 
*' to derived type 'DerivedTemplate<int> *'}}
+  DerivedTemplate<int> *derived_reinterpret = 
reinterpret_cast<DerivedTemplate<int>*>(base);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BaseTemplate<int> 
*' to derived type 'DerivedTemplate<int> *'}}
+  DerivedTemplate<int> *derived_c = (DerivedTemplate<int>*)base;
+  // expected-warning@-1{{Memory unsafe cast from base type 'BaseTemplate<int> 
*' to derived type 'DerivedTemplate<int> *'}}
+  DerivedTemplate<int> &derived_static_ref = 
static_cast<DerivedTemplate<int>&>(base_ref);
+  // expected-warning@-1{{Memory unsafe cast from base type 
'BaseTemplate<int>' to derived type 'DerivedTemplate<int> &'}}
+  DerivedTemplate<int> &derived_reinterpret_ref = 
reinterpret_cast<DerivedTemplate<int>&>(base_ref);
+  // expected-warning@-1{{Memory unsafe cast from base type 
'BaseTemplate<int>' to derived type 'DerivedTemplate<int> &'}}
+  DerivedTemplate<int> &derived_c_ref = (DerivedTemplate<int>&)base_ref;
+  // expected-warning@-1{{Memory unsafe cast from base type 
'BaseTemplate<int>' to derived type 'DerivedTemplate<int> &'}}
+}
+
+#define CAST_MACRO_STATIC(X,Y) (static_cast<Y>(X))
+#define CAST_MACRO_REINTERPRET(X,Y) (reinterpret_cast<Y>(X))
+#define CAST_MACRO_C(X,Y) ((Y)X)
+
+void test_macro_static(Base *base, Derived *derived, Base &base_ref) {
+  Derived *derived_static = CAST_MACRO_STATIC(base, Derived*);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *'}}
+  Derived &derived_static_ref = CAST_MACRO_STATIC(base_ref, Derived&);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &'}}
+  Base *base_static_same = CAST_MACRO_STATIC(base, Base*);  // no warning
+  Base *base_static_upcast = CAST_MACRO_STATIC(derived, Base*);  // no warning
+}
+
+void test_macro_reinterpret(Base *base, Derived *derived, Base &base_ref) {
+  Derived *derived_reinterpret = CAST_MACRO_REINTERPRET(base, Derived*);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *'}}
+  Derived &derived_reinterpret_ref = CAST_MACRO_REINTERPRET(base_ref, 
Derived&);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &' [alpha.webkit.MemoryUnsafeCastChecker]}}
+  Base *base_reinterpret_same = CAST_MACRO_REINTERPRET(base, Base*);  // no 
warning
+  Base *base_reinterpret_upcast = CAST_MACRO_REINTERPRET(derived, Base*);  // 
no warning
+}
+
+void test_macro_c(Base *base, Derived *derived, Base &base_ref) {
+  Derived *derived_c = CAST_MACRO_C(base, Derived*);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base *' to 
derived type 'Derived *' [alpha.webkit.MemoryUnsafeCastChecker]}}
+  Derived &derived_c_ref = CAST_MACRO_C(base_ref, Derived&);
+  // expected-warning@-1{{Memory unsafe cast from base type 'Base' to derived 
type 'Derived &' [alpha.webkit.MemoryUnsafeCastChecker]}}
+  Base *base_c_same = CAST_MACRO_C(base, Base*);  // no warning
+  Base *base_c_upcast = CAST_MACRO_C(derived, Base*);  // no warning
+}
+
+struct BaseStructCpp {
+  int t;
+  void increment() { t++; }
+};
+struct DerivedStructCpp : BaseStructCpp {
+  void increment_t() {increment();}
+};
+
+void test_struct_cpp_pointers(struct BaseStructCpp *base_struct) {
+  struct DerivedStructCpp *derived_static = static_cast<struct 
DerivedStructCpp*>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct 
BaseStructCpp *' to derived type 'struct DerivedStructCpp *'}}
+  struct DerivedStructCpp *derived_reinterpret = reinterpret_cast<struct 
DerivedStructCpp*>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct 
BaseStructCpp *' to derived type 'struct DerivedStructCpp *'}}
+  struct DerivedStructCpp *derived_c = (struct DerivedStructCpp*)base_struct;
+  // expected-warning@-1{{Memory unsafe cast from base type 'struct 
BaseStructCpp *' to derived type 'struct DerivedStructCpp *'}}
+}
+
+typedef struct BaseStructCpp BStructCpp;
+typedef struct DerivedStructCpp DStructCpp;
+
+void test_struct_cpp_refs(BStructCpp &base_struct) {
+  DStructCpp &derived_static = static_cast<DStructCpp&>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStructCpp' to 
derived type 'DStructCpp &'}}
+  DStructCpp &derived_reinterpret = reinterpret_cast<DStructCpp&>(base_struct);
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStructCpp' to 
derived type 'DStructCpp &'}}
+  DStructCpp &derived_c = (DStructCpp&)base_struct;
+  // expected-warning@-1{{Memory unsafe cast from base type 'BStructCpp' to 
derived type 'DStructCpp &'}}
+}
----------------
rniwa wrote:

Can we add a test case for downcast<T>(~) to make sure that won't generate a 
warning?

https://github.com/llvm/llvm-project/pull/114606
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to