1b94fbf083cf82802c9aa7c7a1192be75259cb691philippe#define __STDC_FORMAT_MACROS
28eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <inttypes.h>
3ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <stdio.h>
4ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <unistd.h>
57c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe#include <stdint.h>
67c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe#include <stdlib.h>
7ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include <string>
85bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe#include <sstream>
9ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe#include "../memcheck.h"
10ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// Derived from test provided by Timur Iskhodzhanov (bug 280271)
11ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
12ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippeclass MyClass
13ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
147c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   char m1;
157c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   int  m2;
16ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippepublic:
17ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   ~MyClass()
18ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct MyClass\n");
19ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
20ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
21ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
22ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// Two hierarchies using MI, one with no fields,
23ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe// the other one with some data.
24ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Ae
25ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
26ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Ae()
27ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Ae\n");
28ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
29ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
30ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Be
31ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
32ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Be()
33ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Be\n");
34ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
35ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
36ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct Ce : public Ae, public Be
37ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
38ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~Ce()
39ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct Ce\n");
40ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
41ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
42ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
43ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct A
44ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
45ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char a;
46ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   A()
47ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { a = 'a';
48ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
49ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~A()
50ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct A\n");
51ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
52ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
53ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct B
54ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
55ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char b;
56ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   B()
57ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { b = 'b';
58ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
59ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~B()
60ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct B\n");
61ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
62ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
63ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippestruct C : public A, public B
64ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe{
65ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   char c;
66ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   C()
67ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { c = 'c';
68ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
69ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   virtual ~C()
70ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   { fprintf(stderr, "destruct C\n");
71ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   }
72ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe};
73ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
747c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid* wrap64_malloc(int size)
757c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe{
767c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  uint64_t *p = (uint64_t*)malloc(size + 8);
777c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  *p = size;
787c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  ++p;
797c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  return p;
807c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe}
817c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
827c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid wrap64_free(void *p)
837c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe{
847c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  uint64_t *p2 = (uint64_t*)p;
857c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  if (p2 == NULL)
867c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe    return;
877c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  --p2;
887c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  free(p2);
897c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe}
907c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
91671b0232c307abd80ef4da890c2b00e778751359philippestd::string str;
92671b0232c307abd80ef4da890c2b00e778751359philippestd::string str2;
93671b0232c307abd80ef4da890c2b00e778751359philippeMyClass *ptr;
94671b0232c307abd80ef4da890c2b00e778751359philippeMyClass *ptr2;
95671b0232c307abd80ef4da890c2b00e778751359philippeBe *ptrBCe;
96671b0232c307abd80ef4da890c2b00e778751359philippeAe *ptrACe;
97671b0232c307abd80ef4da890c2b00e778751359philippeB *ptrBC;
98671b0232c307abd80ef4da890c2b00e778751359philippeA *ptrAC;
997c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippevoid* ptr64;
100671b0232c307abd80ef4da890c2b00e778751359philippe
1015bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippechar who_points_at_cmd[100];
102ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
103671b0232c307abd80ef4da890c2b00e778751359philippevoid doit(void)
104671b0232c307abd80ef4da890c2b00e778751359philippe{
105671b0232c307abd80ef4da890c2b00e778751359philippe  str = "Valgrind"; // interior ptr.
106671b0232c307abd80ef4da890c2b00e778751359philippe  str2 = str;
107671b0232c307abd80ef4da890c2b00e778751359philippe  ptr = new MyClass[3]; // interior ptr.
1087c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe  ptr64 = wrap64_malloc(23);
1095bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
1105bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe  // prepare the who_points_at cmd we will run.
1115bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe  // Do it here to avoid having ptr or its exterior ptr kept in a register.
1128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj  sprintf(who_points_at_cmd, "who_points_at %#" PRIxPTR " 20",
1138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj          (uintptr_t) (char*)ptr - sizeof(void*));
1145bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
115671b0232c307abd80ef4da890c2b00e778751359philippe  ptr2 = new MyClass[0]; // "interior but exterior ptr".
116671b0232c307abd80ef4da890c2b00e778751359philippe  // ptr2 points after the chunk, is wrongly considered by memcheck as definitely leaked.
117ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
118671b0232c307abd80ef4da890c2b00e778751359philippe  ptrBCe = new Ce;  // interior ptr.
119671b0232c307abd80ef4da890c2b00e778751359philippe  ptrACe = new Ce;  // not an interior pointer.
120671b0232c307abd80ef4da890c2b00e778751359philippe  ptrBC = new C;  // interior ptr.
121671b0232c307abd80ef4da890c2b00e778751359philippe  ptrAC = new C;  // not an interior pointer.
122671b0232c307abd80ef4da890c2b00e778751359philippe
123671b0232c307abd80ef4da890c2b00e778751359philippe
124671b0232c307abd80ef4da890c2b00e778751359philippe  str2 += " rocks (str2)\n"; // interior ptr.
125671b0232c307abd80ef4da890c2b00e778751359philippe}
126ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
127ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
128671b0232c307abd80ef4da890c2b00e778751359philippeint main() {
129671b0232c307abd80ef4da890c2b00e778751359philippe
130671b0232c307abd80ef4da890c2b00e778751359philippe   doit();
13106bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("v.set log_output");
132ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
133ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "VALGRIND_DO_LEAK_CHECK\n");
134ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   VALGRIND_DO_LEAK_CHECK; // All possible leaks should be detected, giving only reachable data.
135ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
136ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   // Check individually each heuristic
137ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary heuristics multipleinheritance\n");
13806bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance");
139ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary any heuristics newarray\n");
14006bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics newarray");
1417c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics length64\n");
1427c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics length64");
143ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "leak_check summary heuristics stdstring\n");
14406bc722457ffe12e056d2f40d0d2f5c8711b541fflorian   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics stdstring");
145ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
1467c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   // check all and none
1477c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics multipleinheritance,newarray,stdstring,length64\n");
1487c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics multipleinheritance,newarray,stdstring,length64");
1497c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics all\n");
1507c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics all");
1517c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   fprintf(stderr, "leak_check summary heuristics none\n");
1527c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   (void) VALGRIND_MONITOR_COMMAND("leak_check summary heuristics none");
1537c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe
1545bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe   // Test the who_points_at when the block is pointed to with an interior ptr.
1555bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe   (void) VALGRIND_MONITOR_COMMAND(who_points_at_cmd);
1565bd40601a929e8216b1c4b98d5048dddd2c2c20ephilippe
157ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete [] ptr;
158ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete [] ptr2;
159ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrBCe;
160ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrACe;
161ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrBC;
162ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   delete ptrAC;
1637c69a3edda5335fa4c60f8161252b4bab8a76f7ephilippe   wrap64_free(ptr64);
164ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   fprintf(stderr, "Finished!\n");
165ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe   return 0;
166ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe}
167ab1fce9bfb9742bffdfbd7ea9e4dad04ffb17819philippe
168