Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection %s -verify
      2 
      3 extern void clang_analyzer_eval(bool);
      4 extern "C" char *strdup(const char *s);
      5 
      6 namespace PR14054_reduced {
      7   struct Definition;
      8   struct ParseNode {
      9     union {
     10       Definition *lexdef;
     11       ParseNode *data;
     12     } pn_u;
     13   };
     14   struct Definition : public ParseNode { };
     15 
     16   void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
     17     // This used to cause an assertion failure because:
     18     // 1. The implicit operator= for unions assigns all members of the union,
     19     //    not just the active one (b/c there's no way to know which is active).
     20     // 2. RegionStore dutifully stored all the variants at the same offset;
     21     //    the last one won.
     22     // 3. We asked for the value of the first variant but got back a conjured
     23     //    symbol for the second variant.
     24     // 4. We ended up trying to add a base cast to a region of the wrong type.
     25     //
     26     // Now (at the time this test was added), we instead treat all variants of
     27     // a union as different offsets, but only allow one to be active at a time.
     28     *pn = *opn;
     29     x = pn->pn_u.lexdef->pn_u.lexdef;
     30   }
     31 }
     32 
     33 namespace PR14054_original {
     34   struct Definition;
     35   struct ParseNode {
     36     union {
     37       struct {
     38         union {};
     39         Definition *lexdef;
     40       } name;
     41       class {
     42         int *target;
     43         ParseNode *data;
     44       } xmlpi;
     45     } pn_u;
     46   };
     47   struct Definition : public ParseNode { };
     48 
     49   void CloneParseTree(ParseNode *opn, ParseNode *pn,  ParseNode *x) {
     50     pn->pn_u = opn->pn_u;
     51     x = pn->pn_u.name.lexdef->pn_u.name.lexdef;
     52   }
     53 }
     54 
     55 namespace PR17596 {
     56   union IntOrString {
     57     int i;
     58     char *s;
     59   };
     60 
     61   extern void process(IntOrString);
     62 
     63   void test() {
     64     IntOrString uu;
     65     uu.s = strdup("");
     66     process(uu);
     67   }
     68 
     69   void testPositive() {
     70     IntOrString uu;
     71     uu.s = strdup("");
     72   } // expected-warning{{leak}}
     73 
     74   void testCopy() {
     75     IntOrString uu;
     76     uu.i = 4;
     77     clang_analyzer_eval(uu.i == 4); // expected-warning{{TRUE}}
     78 
     79     IntOrString vv;
     80     vv.i = 5;
     81     uu = vv;
     82     // FIXME: Should be true.
     83     clang_analyzer_eval(uu.i == 5); // expected-warning{{UNKNOWN}}
     84   }
     85 
     86   void testInvalidation() {
     87     IntOrString uu;
     88     uu.s = strdup("");
     89 
     90     IntOrString vv;
     91     char str[] = "abc";
     92     vv.s = str;
     93 
     94     // FIXME: This is a leak of uu.s.
     95     uu = vv;
     96   }
     97 
     98   void testIndirectInvalidation() {
     99     IntOrString uu;
    100     char str[] = "abc";
    101     uu.s = str;
    102 
    103     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{TRUE}}
    104 
    105     process(uu);
    106     clang_analyzer_eval(uu.s[0] == 'a'); // expected-warning{{UNKNOWN}}
    107   }
    108 }
    109