Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/include/utils/relptr.h
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * relptr.h
4
 *    This file contains basic declarations for relative pointers.
5
 *
6
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 * src/include/utils/relptr.h
10
 *
11
 *-------------------------------------------------------------------------
12
 */
13
14
#ifndef RELPTR_H
15
#define RELPTR_H
16
17
/*
18
 * Relative pointers are intended to be used when storing an address that may
19
 * be relative either to the base of the process's address space or some
20
 * dynamic shared memory segment mapped therein.
21
 *
22
 * The idea here is that you declare a relative pointer as relptr(type)
23
 * and then use relptr_access to dereference it and relptr_store to change
24
 * it.  The use of a union here is a hack, because what's stored in the
25
 * relptr is always a Size, never an actual pointer.  But including a pointer
26
 * in the union allows us to use stupid macro tricks to provide some measure
27
 * of type-safety.
28
 */
29
#define relptr(type)   union { type *relptr_type; Size relptr_off; }
30
31
/*
32
 * pgindent gets confused by declarations that use "relptr(type)" directly,
33
 * so preferred style is to write
34
 *    typedef struct ... SomeStruct;
35
 *    relptr_declare(SomeStruct, RelptrSomeStruct);
36
 * and then declare pointer variables as "RelptrSomeStruct someptr".
37
 */
38
#define relptr_declare(type, relptrtype) \
39
  typedef relptr(type) relptrtype
40
41
#ifdef HAVE_TYPEOF
42
#define relptr_access(base, rp) \
43
0
  (StaticAssertVariableIsOfTypeMacro(base, char *), \
44
0
   (typeof((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
45
0
    (base) + (rp).relptr_off - 1))
46
#else
47
#define relptr_access(base, rp) \
48
  (StaticAssertVariableIsOfTypeMacro(base, char *), \
49
   (void *) ((rp).relptr_off == 0 ? NULL : (base) + (rp).relptr_off - 1))
50
#endif
51
52
#define relptr_is_null(rp) \
53
0
  ((rp).relptr_off == 0)
54
55
#define relptr_offset(rp) \
56
0
  ((rp).relptr_off - 1)
57
58
/* We use this inline to avoid double eval of "val" in relptr_store */
59
static inline Size
60
relptr_store_eval(char *base, char *val)
61
0
{
62
0
  if (val == NULL)
63
0
    return 0;
64
0
  else
65
0
  {
66
0
    Assert(val >= base);
67
0
    return val - base + 1;
68
0
  }
69
0
}
Unexecuted instantiation: dsm.c:relptr_store_eval
Unexecuted instantiation: dsa.c:relptr_store_eval
Unexecuted instantiation: freepage.c:relptr_store_eval
70
71
#ifdef HAVE_TYPEOF
72
#define relptr_store(base, rp, val) \
73
0
  (StaticAssertVariableIsOfTypeMacro(base, char *), \
74
0
   StaticAssertVariableIsOfTypeMacro(val, typeof((rp).relptr_type)), \
75
0
   (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
76
#else
77
#define relptr_store(base, rp, val) \
78
  (StaticAssertVariableIsOfTypeMacro(base, char *), \
79
   (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
80
#endif
81
82
#define relptr_copy(rp1, rp2) \
83
0
  ((rp1).relptr_off = (rp2).relptr_off)
84
85
#endif              /* RELPTR_H */