xref: /llvm-project/clang/test/Analysis/cast-to-struct.cpp (revision cf715bd33006599db3b6d472bdf6bbe40a616dd0)
1184c6242SDominic Chen // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.CastToStruct,core -verify %s
213264ebeSDaniel Marjamaki 
313264ebeSDaniel Marjamaki struct AB {
413264ebeSDaniel Marjamaki   int A;
513264ebeSDaniel Marjamaki   int B;
613264ebeSDaniel Marjamaki };
713264ebeSDaniel Marjamaki 
813264ebeSDaniel Marjamaki struct ABC {
913264ebeSDaniel Marjamaki   int A;
1013264ebeSDaniel Marjamaki   int B;
1113264ebeSDaniel Marjamaki   int C;
1213264ebeSDaniel Marjamaki };
1313264ebeSDaniel Marjamaki 
1413264ebeSDaniel Marjamaki struct Base {
BaseBase1513264ebeSDaniel Marjamaki   Base() : A(0), B(0) {}
~BaseBase1613264ebeSDaniel Marjamaki   virtual ~Base() {}
1713264ebeSDaniel Marjamaki 
1813264ebeSDaniel Marjamaki   int A;
1913264ebeSDaniel Marjamaki   int B;
2013264ebeSDaniel Marjamaki };
2113264ebeSDaniel Marjamaki 
2213264ebeSDaniel Marjamaki struct Derived : public Base {
DerivedDerived2313264ebeSDaniel Marjamaki   Derived() : Base(), C(0) {}
2413264ebeSDaniel Marjamaki   int C;
2513264ebeSDaniel Marjamaki };
2613264ebeSDaniel Marjamaki 
structToStruct(struct AB * P)2713264ebeSDaniel Marjamaki void structToStruct(struct AB *P) {
2813264ebeSDaniel Marjamaki   struct AB Ab;
2913264ebeSDaniel Marjamaki   struct ABC *Abc;
3013264ebeSDaniel Marjamaki   Abc = (struct ABC *)&Ab; // expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
3113264ebeSDaniel Marjamaki   Abc = (struct ABC *)P; // No warning; It is not known what data P points at.
3213264ebeSDaniel Marjamaki   Abc = (struct ABC *)&*P;
3313264ebeSDaniel Marjamaki 
3413264ebeSDaniel Marjamaki   // Don't warn when the cast is not widening.
3513264ebeSDaniel Marjamaki   P = (struct AB *)&Ab; // struct AB * => struct AB *
3613264ebeSDaniel Marjamaki   struct ABC Abc2;
3713264ebeSDaniel Marjamaki   P = (struct AB *)&Abc2; // struct ABC * => struct AB *
3813264ebeSDaniel Marjamaki 
3913264ebeSDaniel Marjamaki   // True negatives when casting from Base to Derived.
4013264ebeSDaniel Marjamaki   Derived D1, *D2;
4113264ebeSDaniel Marjamaki   Base &B1 = D1;
4213264ebeSDaniel Marjamaki   D2 = (Derived *)&B1;
4313264ebeSDaniel Marjamaki   D2 = dynamic_cast<Derived *>(&B1);
4413264ebeSDaniel Marjamaki   D2 = static_cast<Derived *>(&B1);
4513264ebeSDaniel Marjamaki 
4613264ebeSDaniel Marjamaki   // True positives when casting from Base to Derived.
4713264ebeSDaniel Marjamaki   Base B2;
4813264ebeSDaniel Marjamaki   D2 = (Derived *)&B2;// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
4913264ebeSDaniel Marjamaki   D2 = dynamic_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
5013264ebeSDaniel Marjamaki   D2 = static_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
5113264ebeSDaniel Marjamaki 
5213264ebeSDaniel Marjamaki   // False negatives, cast from Base to Derived. With path sensitive analysis
5313264ebeSDaniel Marjamaki   // these false negatives could be fixed.
5413264ebeSDaniel Marjamaki   Base *B3 = &B2;
5513264ebeSDaniel Marjamaki   D2 = (Derived *)B3;
5613264ebeSDaniel Marjamaki   D2 = dynamic_cast<Derived *>(B3);
5713264ebeSDaniel Marjamaki   D2 = static_cast<Derived *>(B3);
5813264ebeSDaniel Marjamaki }
5913264ebeSDaniel Marjamaki 
intToStruct(int * P)6013264ebeSDaniel Marjamaki void intToStruct(int *P) {
6113264ebeSDaniel Marjamaki   struct ABC *Abc;
6213264ebeSDaniel Marjamaki   Abc = (struct ABC *)P; // expected-warning {{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
6313264ebeSDaniel Marjamaki 
6413264ebeSDaniel Marjamaki   // Cast from void *.
6513264ebeSDaniel Marjamaki   void *VP = P;
6613264ebeSDaniel Marjamaki   Abc = (struct ABC *)VP;
6713264ebeSDaniel Marjamaki }
68*cf715bd3SDaniel Marjamaki 
69*cf715bd3SDaniel Marjamaki // https://llvm.org/bugs/show_bug.cgi?id=31173
dontCrash1(struct AB X)70*cf715bd3SDaniel Marjamaki void dontCrash1(struct AB X) {
71*cf715bd3SDaniel Marjamaki   struct UndefS *S = (struct UndefS *)&X;
72*cf715bd3SDaniel Marjamaki }
73*cf715bd3SDaniel Marjamaki 
74*cf715bd3SDaniel Marjamaki struct S;
75*cf715bd3SDaniel Marjamaki struct T {
76*cf715bd3SDaniel Marjamaki   struct S *P;
77*cf715bd3SDaniel Marjamaki };
78*cf715bd3SDaniel Marjamaki extern struct S Var1, Var2;
dontCrash2()79*cf715bd3SDaniel Marjamaki void dontCrash2() {
80*cf715bd3SDaniel Marjamaki   ((struct T *) &Var1)->P = &Var2;
81*cf715bd3SDaniel Marjamaki }
82