1ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <stdio.h>
2ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <unistd.h>
37c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe#include <stdint.h>
47c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe#include <stdlib.h>
5ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <string>
65bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe#include <sstream>
7ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include "../memcheck.h"
8ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// Derived from test provided by Timur Iskhodzhanov (bug 280271)
9ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
10ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippeclass MyClass
11ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
127c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   char m1;
137c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   int  m2;
14ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippepublic:
15ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   ~MyClass()
16ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct MyClass\n");
17ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
18ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
19ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
20ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// Two hierarchies using MI, one with no fields,
21ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// the other one with some data.
22ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Ae
23ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
24ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Ae()
25ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Ae\n");
26ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
27ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
28ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Be
29ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
30ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Be()
31ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Be\n");
32ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
33ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
34ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Ce : public Ae, public Be
35ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
36ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Ce()
37ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Ce\n");
38ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
39ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
40ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
41ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct A
42ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
43ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char a;
44ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   A()
45ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { a = 'a';
46ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
47ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~A()
48ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct A\n");
49ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
50ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
51ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct B
52ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
53ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char b;
54ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   B()
55ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { b = 'b';
56ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
57ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~B()
58ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct B\n");
59ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
60ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
61ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct C : public A, public B
62ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
63ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char c;
64ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   C()
65ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { c = 'c';
66ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
67ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~C()
68ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct C\n");
69ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
70ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
71ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
727c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid* wrap64_malloc(int size)
737c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe{
747c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  uint64_t *p = (uint64_t*)malloc(size + 8);
757c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  *p = size;
767c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  ++p;
777c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  return p;
787c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe}
797c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
807c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid wrap64_free(void *p)
817c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe{
827c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  uint64_t *p2 = (uint64_t*)p;
837c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  if (p2 == NULL)
847c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe    return;
857c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  --p2;
867c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  free(p2);
877c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe}
887c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
89671b0232c307abd80ef4da890c2b00e778751359philippestd::string str;
90671b0232c307abd80ef4da890c2b00e778751359philippestd::string str2;
91671b0232c307abd80ef4da890c2b00e778751359philippeMyClass *ptr;
92671b0232c307abd80ef4da890c2b00e778751359philippeMyClass *ptr2;
93671b0232c307abd80ef4da890c2b00e778751359philippeBe *ptrBCe;
94671b0232c307abd80ef4da890c2b00e778751359philippeAe *ptrACe;
95671b0232c307abd80ef4da890c2b00e778751359philippeB *ptrBC;
96671b0232c307abd80ef4da890c2b00e778751359philippeA *ptrAC;
977c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid* ptr64;
98671b0232c307abd80ef4da890c2b00e778751359philippe
995bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippechar who_points_at_cmd[100];
100ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
101671b0232c307abd80ef4da890c2b00e778751359philippevoid doit(void)
102671b0232c307abd80ef4da890c2b00e778751359philippe{
103671b0232c307abd80ef4da890c2b00e778751359philippe  str = "Valgrind"; // interior ptr.
104671b0232c307abd80ef4da890c2b00e778751359philippe  str2 = str;
105671b0232c307abd80ef4da890c2b00e778751359philippe  ptr = new MyClass[3]; // interior ptr.
1067c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  ptr64 = wrap64_malloc(23);
1075bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
1085bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe  // prepare the who_points_at cmd we will run.
1095bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe  // Do it here to avoid having ptr or its exterior ptr kept in a register.
1105bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe  sprintf(who_points_at_cmd, "who_points_at %p 20", (char*)ptr - sizeof(void*));
1115bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
112671b0232c307abd80ef4da890c2b00e778751359philippe  ptr2 = new MyClass[0]; // "interior but exterior ptr".
113671b0232c307abd80ef4da890c2b00e778751359philippe  // ptr2 points after the chunk, is wrongly considered by memcheck as definitely leaked.
114ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
115671b0232c307abd80ef4da890c2b00e778751359philippe  ptrBCe = new Ce;  // interior ptr.
116671b0232c307abd80ef4da890c2b00e778751359philippe  ptrACe = new Ce;  // not an interior pointer.
117671b0232c307abd80ef4da890c2b00e778751359philippe  ptrBC = new C;  // interior ptr.
118671b0232c307abd80ef4da890c2b00e778751359philippe  ptrAC = new C;  // not an interior pointer.
119671b0232c307abd80ef4da890c2b00e778751359philippe
120671b0232c307abd80ef4da890c2b00e778751359philippe
121671b0232c307abd80ef4da890c2b00e778751359philippe  str2 += " rocks (str2)\n"; // interior ptr.
122671b0232c307abd80ef4da890c2b00e778751359philippe}
123ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
124ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
125671b0232c307abd80ef4da890c2b00e778751359philippeint main() {
126671b0232c307abd80ef4da890c2b00e778751359philippe
127671b0232c307abd80ef4da890c2b00e778751359philippe   doit();
12806bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("v.set log_output");
129ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
130ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "VALGRIND_DO_LEAK_CHECK\n");
131ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   VALGRIND_DO_LEAK_CHECK; // All possible leaks should be detected, giving only reachable data.
132ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
133ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   // Check individually each heuristic
134ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary heuristics multipleinheritance\n");
13506bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance");
136ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary any heuristics newarray\n");
13706bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics newarray");
1387c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics length64\n");
1397c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics length64");
140ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary heuristics stdstring\n");
14106bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics stdstring");
142ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
1437c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   // check all and none
1447c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics multipleinheritance,newarray,stdstring,length64\n");
1457c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance,newarray,stdstring,length64");
1467c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics all\n");
1477c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics all");
1487c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics none\n");
1497c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics none");
1507c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
1515bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe   // Test the who_points_at when the block is pointed to with an interior ptr.
1525bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe   (void) VALGRIND_MONITOR_COMMAND(who_points_at_cmd);
1535bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
154ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete [] ptr;
155ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete [] ptr2;
156ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrBCe;
157ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrACe;
158ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrBC;
159ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrAC;
1607c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   wrap64_free(ptr64);
161ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "Finished!\n");
162ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   return 0;
163ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe}
164ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
165