aboutsummaryrefslogtreecommitdiff
path: root/odb/gcc.hxx
blob: f4780ba23deb0cc72d393b29d4990e025b1dff44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// file      : odb/gcc.hxx
// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
// license   : GNU GPL v3; see accompanying LICENSE file

#ifndef ODB_GCC_HXX
#define ODB_GCC_HXX

#include <odb/gcc-fwd.hxx>

// Actually, let's keep it out. With it included we can compile in C++98
// but not in C++14 (GCC 6 default).
//
// #if BUILDING_GCC_MAJOR >= 6
// #  include <safe-ctype.h> // See gcc-fwd.hxx.
// #endif

// GCC header includes to get the plugin and parse tree declarations.
// The order is important and doesn't follow any kind of logic.
//

#include <stdlib.h>
#include <gmp.h>

#include <cstdlib> // Include before GCC poisons some declarations.

// GCC 4.7 can be built using either C or C++ compiler. From 4.8 it
// is always built as C++.
//
#if BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR <= 6
#  define ODB_GCC_PLUGIN_C
#elif BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR <= 7
#  include <config.h>
#  ifndef ENABLE_BUILD_WITH_CXX
#    define ODB_GCC_PLUGIN_C
#  endif
#endif

#ifdef ODB_GCC_PLUGIN_C
extern "C"
{
#endif

// GCC's system.h below includes safe-ctype.h which "disables" versions
// from ctype.h. Well, now it's gonna learn how it feels to be disabled.
//
#define SAFE_CTYPE_H

#include <gcc-plugin.h>

#include <config.h>
#include <system.h>
#include <coretypes.h>
#include <tree.h>
#include <real.h>

#include <cpplib.h>
#include <cp/cp-tree.h>

#if BUILDING_GCC_MAJOR > 4 || BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR > 5
#  include <c-family/c-common.h>
#  include <c-family/c-pragma.h>
#else
#  include <c-common.h>
#  include <c-pragma.h>
#endif

#if BUILDING_GCC_MAJOR > 4 || BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR > 8
#  include <stringpool.h> // get_identifier
#endif

#include <diagnostic.h>
#include <output.h>

#ifdef ODB_GCC_PLUGIN_C
} // extern "C"
#endif

// Get the value of INTEGER_CST reinterpreted as unsigned.
//
inline unsigned long long
integer_value (tree n)
{
  unsigned long long val;

#if BUILDING_GCC_MAJOR >= 5
  if (tree_fits_uhwi_p (n))
    val = static_cast<unsigned long long> (tree_to_uhwi (n));
  else
    val = static_cast<unsigned long long> (tree_to_shwi (n));
#else
  HOST_WIDE_INT hwl (TREE_INT_CST_LOW (n));
  HOST_WIDE_INT hwh (TREE_INT_CST_HIGH (n));
  unsigned short width (HOST_BITS_PER_WIDE_INT);

  if (hwh == 0)
    val = static_cast<unsigned long long> (hwl);
  else if (hwh == -1 && hwl != 0)
    val = static_cast<unsigned long long> (hwl);
  else
    val = static_cast<unsigned long long> ((hwh << width) + hwl);
#endif

  return val;
}

// Since 4.7.0 the location may point inside a macro rather than at
// the expansion point. We are only really interested in the expansion
// points so we use the real_source_location() wrapper rather than
// DECL_SOURCE_LOCATION() to do this at the source.
//
inline location_t
real_source_location (tree n)
{
  location_t l (DECL_SOURCE_LOCATION (n));

#if BUILDING_GCC_MAJOR > 4 || BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR > 6
  l = linemap_resolve_location (line_table, l, LRK_MACRO_EXPANSION_POINT, 0);
#endif

  return l;
}

// In 4.9.0 the tree code type was changed from int to enum tree_code.
// the tree_code_name array is also gone with the get_tree_code_name()
// function in its place.
//
#if BUILDING_GCC_MAJOR > 4 || BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR > 8
typedef enum tree_code gcc_tree_code_type;

inline const char*
gcc_tree_code_name (gcc_tree_code_type tc) {return get_tree_code_name (tc);}
#else
typedef int gcc_tree_code_type;

inline const char*
gcc_tree_code_name (gcc_tree_code_type tc) {return tree_code_name[tc];}
#endif

// Only since GCC 4.7.0.
//
#ifndef LOCATION_COLUMN
#define LOCATION_COLUMN(LOC) (expand_location (LOC).column)
#endif

#ifndef DECL_SOURCE_COLUMN
#define DECL_SOURCE_COLUMN(NODE) LOCATION_COLUMN (DECL_SOURCE_LOCATION (NODE))
#endif

// Only since GCC 4.6.0.
//
#ifndef DECL_CHAIN
#define DECL_CHAIN(x) TREE_CHAIN(x)
#endif

// In GCC 6, ANON_AGGRNAME_P became anon_aggrname_p().
//
#if BUILDING_GCC_MAJOR < 6
#  define anon_aggrname_p(X) ANON_AGGRNAME_P(X)
#endif

// In GCC 9:
//
// INCLUDED_FROM     Became linemap_included_from_linemap().
// LAST_SOURCE_LINE  Was removed apparently as no longer used. Studying
//                   the line-map.h diff from 8.3 suggests that the old
//                   implementation should still work.
//
#if BUILDING_GCC_MAJOR >= 9

inline const line_map_ordinary*
INCLUDED_FROM (line_maps* set, const line_map_ordinary* map)
{
  return linemap_included_from_linemap (set, map);
}

inline source_location
LAST_SOURCE_LINE_LOCATION (const line_map_ordinary* map)
{
  return (((map[1].start_location - 1
	    - map->start_location)
	   & ~((1 << map->m_column_and_range_bits) - 1))
	  + map->start_location);
}

inline linenum_type
LAST_SOURCE_LINE (const line_map_ordinary* map)
{
  return SOURCE_LINE (map, LAST_SOURCE_LINE_LOCATION (map));
}

#endif

#endif // ODB_GCC_HXX