• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ivmai / bdwgc / 1485

17 Apr 2023 05:30PM UTC coverage: 76.519% (+0.02%) from 76.502%
1485

push

travis-ci-com

ivmai
Prevent 'function should return a value' BCC error in CMake script

* CMakeLists.txt [enable_werror && BORLAND && enable_threads]: Pass
"/w-rvl" to add_compile_options; add comment.

7772 of 10157 relevant lines covered (76.52%)

8798128.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.52
/tests/cpp.cc
1
/*
2
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
3
 *
4
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6
 *
7
 * Permission is hereby granted to use or copy this program
8
 * for any purpose, provided the above notices are retained on all copies.
9
 * Permission to modify the code and to distribute modified code is granted,
10
 * provided the above notices are retained, and a notice that the code was
11
 * modified is included with the above copyright notice.
12
 */
13

14
// This program tries to test the specific C++ functionality provided by
15
// gc_cpp.h that isn't tested by the more general test routines of the
16
// collector.
17

18
#ifdef HAVE_CONFIG_H
19
# include "config.h"
20
#endif
21

22
#undef GC_BUILD
23

24
#define GC_DONT_INCL_WINDOWS_H
25
#include "gc_cpp.h"
26

27
#include <stdlib.h>
28
#include <string.h>
29

30
#define GC_NAMESPACE_ALLOCATOR
31
#include "gc/gc_allocator.h"
32
using boehmgc::gc_allocator;
33
using boehmgc::gc_allocator_ignore_off_page;
34
using boehmgc::traceable_allocator;
35

36
# include "private/gcconfig.h"
37

38
# ifndef GC_API_PRIV
39
#   define GC_API_PRIV GC_API
40
# endif
41
extern "C" {
42
  GC_API_PRIV void GC_printf(const char * format, ...);
43
  /* Use GC private output to reach the same log file.  */
44
  /* Don't include gc_priv.h, since that may include Windows system     */
45
  /* header files that don't take kindly to this context.               */
46
}
47

48
#ifdef MSWIN32
49
# ifndef WIN32_LEAN_AND_MEAN
50
#   define WIN32_LEAN_AND_MEAN 1
51
# endif
52
# define NOSERVICE
53
# include <windows.h>
54
#endif
55

56
#ifdef GC_NAME_CONFLICT
57
# define USE_GC GC_NS_QUALIFY(UseGC)
58
  struct foo * GC;
59
#else
60
# define USE_GC GC_NS_QUALIFY(GC)
61
#endif
62

63
#define my_assert( e ) \
64
    if (! (e)) { \
65
        GC_printf( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
66
                    __LINE__ ); \
67
        exit( 1 ); }
68

69
#if defined(__powerpc64__) && !defined(__clang__) && GC_GNUC_PREREQ(10, 0)
70
  /* Suppress "layout of aggregates ... has changed" GCC note. */
71
# define A_I_TYPE short
72
#else
73
# define A_I_TYPE int
74
#endif
75

76
class A {public:
77
    /* An uncollectible class. */
78

79
    GC_ATTR_EXPLICIT A(int iArg): i(static_cast<A_I_TYPE>(iArg)) {}
42,224,000✔
80
    void Test( int iArg ) {
223,986✔
81
        my_assert( i == iArg );}
223,986✔
82
    virtual ~A() {}
1,637,986✔
83
    A_I_TYPE i; };
84

85

86
class B: public GC_NS_QUALIFY(gc), public A { public:
87
    /* A collectible class. */
88

89
    GC_ATTR_EXPLICIT B( int j ): A( j ) {}
28,014,000✔
90
    virtual ~B() {
4,242,000✔
91
        my_assert( deleting );}
4,242,000✔
92
    static void Deleting( int on ) {
2,828,000✔
93
        deleting = on;}
2,828,000✔
94
    static int deleting;};
95

96
int B::deleting = 0;
97

98
#define C_INIT_LEFT_RIGHT(arg_l, arg_r) \
99
    { \
100
        C *l = new C(arg_l); \
101
        C *r = new C(arg_r); \
102
        left = l; \
103
        right = r; \
104
        if (GC_is_heap_ptr(this)) { \
105
            GC_END_STUBBORN_CHANGE(this); \
106
            GC_reachable_here(l); \
107
            GC_reachable_here(r); \
108
        } \
109
    }
110

111
class C: public GC_NS_QUALIFY(gc_cleanup), public A { public:
112
    /* A collectible class with cleanup and virtual multiple inheritance. */
113

114
    // The class uses dynamic memory/resource allocation, so provide both
115
    // a copy constructor and an assignment operator to workaround a cppcheck
116
    // warning.
117
    C(const C& c) : A(c.i), level(c.level), left(0), right(0) {
118
        if (level > 0)
119
            C_INIT_LEFT_RIGHT(*c.left, *c.right);
120
    }
121

122
    C& operator=(const C& c) {
123
        if (this != &c) {
124
            delete left;
125
            delete right;
126
            i = c.i;
127
            level = c.level;
128
            left = 0;
129
            right = 0;
130
            if (level > 0)
131
                C_INIT_LEFT_RIGHT(*c.left, *c.right);
132
        }
133
        return *this;
134
    }
135

136
    GC_ATTR_EXPLICIT C( int levelArg ): A( levelArg ), level( levelArg ) {
196,000✔
137
        nAllocated++;
196,000✔
138
        if (level > 0) {
196,000✔
139
            C_INIT_LEFT_RIGHT(level - 1, level - 1);
84,000✔
140
        } else {
141
            left = right = 0;}}
112,000✔
142
    ~C() {
393,372✔
143
        this->A::Test( level );
195,986✔
144
        nFreed++;
195,986✔
145
        my_assert( level == 0 ?
195,986✔
146
                   left == 0 && right == 0 :
147
                   level == left->level + 1 && level == right->level + 1 );
148
        left = right = 0;
195,986✔
149
        level = -123456;}
393,372✔
150
    static void Test() {
14✔
151
        if (GC_is_incremental_mode() && nFreed < (nAllocated / 5) * 4) {
14✔
152
          // An explicit GC might be needed to reach the expected number
153
          // of the finalized objects.
154
          GC_gcollect();
×
155
        }
156
        my_assert(nFreed <= nAllocated);
14✔
157
#       ifndef GC_NO_FINALIZATION
158
            my_assert(nFreed >= (nAllocated / 5) * 4 || GC_get_find_leak());
14✔
159
#       endif
160
    }
14✔
161

162
    static int nFreed;
163
    static int nAllocated;
164
    int level;
165
    C* left;
166
    C* right;};
167

168
int C::nFreed = 0;
169
int C::nAllocated = 0;
170

171

172
class D: public GC_NS_QUALIFY(gc) { public:
173
    /* A collectible class with a static member function to be used as
174
    an explicit clean-up function supplied to ::new. */
175

176
    GC_ATTR_EXPLICIT D( int iArg ): i( iArg ) {
14,000✔
177
        nAllocated++;}
14,000✔
178
    static void CleanUp( void* obj, void* data ) {
13,998✔
179
        D* self = static_cast<D*>(obj);
13,998✔
180
        nFreed++;
13,998✔
181
        my_assert(static_cast<GC_word>(self->i)
13,998✔
182
                    == reinterpret_cast<GC_word>(data));
183
    }
13,998✔
184
    static void Test() {
14✔
185
#       ifndef GC_NO_FINALIZATION
186
            my_assert(nFreed >= (nAllocated / 5) * 4 || GC_get_find_leak());
14✔
187
#       endif
188
    }
14✔
189

190
    int i;
191
    static int nFreed;
192
    static int nAllocated;};
193

194
int D::nFreed = 0;
195
int D::nAllocated = 0;
196

197

198
class E: public GC_NS_QUALIFY(gc_cleanup) { public:
199
    /* A collectible class with clean-up for use by F. */
200

201
    E() {
28,000✔
202
        nAllocated++;}
28,000✔
203
    ~E() {
55,992✔
204
        nFreed++;}
55,992✔
205

206
    static int nFreed;
207
    static int nAllocated;};
208

209
int E::nFreed = 0;
210
int E::nAllocated = 0;
211

212

213
class F: public E {public:
214
    /* A collectible class with clean-up, a base with clean-up, and a
215
    member with clean-up. */
216

217
    F() {
14,000✔
218
        nAllocatedF++;
14,000✔
219
    }
14,000✔
220

221
    ~F() {
27,996✔
222
        nFreedF++;
13,998✔
223
    }
13,998✔
224

225
    static void Test() {
14✔
226
#       ifndef GC_NO_FINALIZATION
227
            my_assert(nFreedF >= (nAllocatedF / 5) * 4 || GC_get_find_leak());
14✔
228
#       endif
229
        my_assert(2 * nFreedF == nFreed);
14✔
230
    }
14✔
231

232
    E e;
233
    static int nFreedF;
234
    static int nAllocatedF;
235
};
236

237
int F::nFreedF = 0;
238
int F::nAllocatedF = 0;
239

240

241
GC_word Disguise( void* p ) {
28,000✔
242
    return GC_HIDE_POINTER(p);
28,000✔
243
}
244

245
void* Undisguise( GC_word i ) {
28,000✔
246
    return GC_REVEAL_POINTER(i);
28,000✔
247
}
248

249
#define GC_CHECKED_DELETE(p) \
250
    { \
251
      size_t freed_before = GC_get_expl_freed_bytes_since_gc(); \
252
      delete p; /* the operator should invoke GC_FREE() */ \
253
      size_t freed_after = GC_get_expl_freed_bytes_since_gc(); \
254
      my_assert(freed_before != freed_after); \
255
    }
256

257
#define N_TESTS 7
258

259
#if ((defined(MSWIN32) && !defined(__MINGW32__)) || defined(MSWINCE)) \
260
    && !defined(NO_WINMAIN_ENTRY)
261
  int APIENTRY WinMain( HINSTANCE /* instance */, HINSTANCE /* prev */,
262
                       LPSTR cmd, int /* cmdShow */)
263
  {
264
    int argc = 0;
265
    char* argv[ 3 ];
266

267
#   if defined(CPPCHECK)
268
      GC_noop1(reinterpret_cast<GC_word>(&WinMain));
269
#   endif
270
    if (cmd != 0)
271
      for (argc = 1; argc < static_cast<int>(sizeof(argv) / sizeof(argv[0]));
272
           argc++) {
273
        // Parse the command-line string.  Non-reentrant strtok() is not used
274
        // to avoid complains of static analysis tools.  (And, strtok_r() is
275
        // not available on some platforms.)  The code is equivalent to:
276
        //   if (!(argv[argc] = strtok(argc == 1 ? cmd : 0, " \t"))) break;
277
        if (NULL == cmd) {
278
          argv[argc] = NULL;
279
          break;
280
        }
281
        for (; *cmd != '\0'; cmd++) {
282
          if (*cmd != ' ' && *cmd != '\t')
283
            break;
284
        }
285
        if ('\0' == *cmd) {
286
          argv[argc] = NULL;
287
          break;
288
        }
289
        argv[argc] = cmd;
290
        while (*(++cmd) != '\0') {
291
          if (*cmd == ' ' || *cmd == '\t')
292
            break;
293
        }
294
        if (*cmd != '\0') {
295
          *(cmd++) = '\0';
296
        } else {
297
          cmd = NULL;
298
        }
299
      }
300
#elif defined(MACOS)
301
  int main() {
302
    char* argv_[] = {"cpptest", "7"}; // MacOS doesn't have a command line
303
    argv = argv_;
304
    argc = sizeof(argv_) / sizeof(argv_[0]);
305
#else
306
  int main( int argc, char* argv[] ) {
2✔
307
#endif
308

309
    GC_set_all_interior_pointers(1);
2✔
310
                        /* needed due to C++ multiple inheritance used  */
311

312
#   ifdef TEST_MANUAL_VDB
313
      GC_set_manual_vdb_allowed(1);
314
#   endif
315
    GC_INIT();
2✔
316
#   ifndef NO_INCREMENTAL
317
      GC_enable_incremental();
2✔
318
#   endif
319
    if (GC_get_find_leak())
2✔
320
      GC_printf("This test program is not designed for leak detection mode\n");
×
321

322
    int i, iters, n;
323
    int *x = gc_allocator<int>().allocate(1);
2✔
324
    int *xio;
325
    xio = gc_allocator_ignore_off_page<int>().allocate(1);
2✔
326
    GC_reachable_here(xio);
2✔
327
    int **xptr = traceable_allocator<int *>().allocate(1);
2✔
328
    *x = 29;
2✔
329
    if (!xptr) {
2✔
330
      GC_printf("Out of memory!\n");
×
331
      exit(3);
×
332
    }
333
    GC_PTR_STORE_AND_DIRTY(xptr, x);
2✔
334
    x = 0;
2✔
335
    if (argc != 2
2✔
336
        || (n = atoi(argv[1])) <= 0) {
2✔
337
      GC_printf("usage: cpptest <number-of-iterations>\n"
338
                "Assuming %d iterations\n", N_TESTS);
2✔
339
      n = N_TESTS;
2✔
340
    }
341
#   ifdef LINT2
342
      if (n > 100 * 1000) n = 100 * 1000;
343
#   endif
344

345
    for (iters = 1; iters <= n; iters++) {
16✔
346
        GC_printf( "Starting iteration %d\n", iters );
14✔
347

348
            /* Allocate some uncollectible As and disguise their pointers.
349
            Later we'll check to see if the objects are still there.  We're
350
            checking to make sure these objects really are uncollectible. */
351
        GC_word as[ 1000 ];
352
        GC_word bs[ 1000 ];
353
        for (i = 0; i < 1000; i++) {
14,014✔
354
            as[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) A(i) );
14,000✔
355
            bs[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) B(i) ); }
14,000✔
356

357
            /* Allocate a fair number of finalizable Cs, Ds, and Fs.
358
            Later we'll check to make sure they've gone away. */
359
        for (i = 0; i < 1000; i++) {
14,014✔
360
            C* c = new C( 2 );
14,000✔
361
            C c1( 2 );           /* stack allocation should work too */
28,000✔
362
            D* d;
363
            F* f;
364
            d = ::new (USE_GC, D::CleanUp,
365
                       reinterpret_cast<void*>(static_cast<GC_word>(i))) D(i);
14,000✔
366
            GC_reachable_here(d);
14,000✔
367
            f = new F;
14,000✔
368
            F** fa = new F*[1];
14,000✔
369
            fa[0] = f;
14,000✔
370
            (void)fa;
371
            delete[] fa;
14,000✔
372
            if (0 == i % 10)
14,000✔
373
                GC_CHECKED_DELETE(c);
1,400✔
374
        }
375

376
            /* Allocate a very large number of collectible As and Bs and
377
            drop the references to them immediately, forcing many
378
            collections. */
379
        for (i = 0; i < 1000000; i++) {
14,000,014✔
380
            A* a;
381
            a = new (USE_GC) A( i );
14,000,000✔
382
            GC_reachable_here(a);
14,000,000✔
383
            B* b;
384
            b = new B( i );
14,000,000✔
385
            (void)b;
386
            b = new (USE_GC) B( i );
14,000,000✔
387
            if (0 == i % 10) {
14,000,000✔
388
                B::Deleting( 1 );
1,400,000✔
389
                GC_CHECKED_DELETE(b);
1,400,000✔
390
                B::Deleting( 0 );}
1,400,000✔
391
#           if defined(FINALIZE_ON_DEMAND) && !defined(GC_NO_FINALIZATION)
392
              GC_invoke_finalizers();
393
#           endif
394
            }
395

396
            /* Make sure the uncollectible As and Bs are still there. */
397
        for (i = 0; i < 1000; i++) {
14,014✔
398
            A* a = static_cast<A*>(Undisguise(as[i]));
14,000✔
399
            B* b = static_cast<B*>(Undisguise(bs[i]));
14,000✔
400
            a->Test( i );
14,000✔
401
#           if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
402
              // Workaround for ASan/MSan: the linker uses operator delete
403
              // implementation from libclang_rt instead of gc_cpp (thus
404
              // causing incompatible alloc/free).
405
              GC_FREE(a);
406
#           else
407
              GC_CHECKED_DELETE(a);
14,000✔
408
#           endif
409
            b->Test( i );
14,000✔
410
            B::Deleting( 1 );
14,000✔
411
            GC_CHECKED_DELETE(b);
14,000✔
412
            B::Deleting( 0 );
14,000✔
413
#           if defined(FINALIZE_ON_DEMAND) && !defined(GC_NO_FINALIZATION)
414
                 GC_invoke_finalizers();
415
#           endif
416
            }
417

418
            /* Make sure most of the finalizable Cs, Ds, and Fs have
419
            gone away. */
420
        C::Test();
14✔
421
        D::Test();
14✔
422
        F::Test();}
14✔
423

424
    x = *xptr;
2✔
425
    my_assert(29 == x[0]);
2✔
426
    GC_printf("The test appears to have succeeded.\n");
2✔
427
    return 0;
2✔
428
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc