Line data Source code
1 : /* Logical location support, without knowledge of "tree".
2 : Copyright (C) 2022-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
22 : #define GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
23 :
24 : #include "label-text.h"
25 :
26 : namespace diagnostics {
27 : namespace logical_locations {
28 :
29 : /* An enum for discriminating between different kinds of logical location
30 : for a diagnostic.
31 :
32 : Roughly corresponds to logicalLocation's "kind" property in SARIF v2.1.0
33 : (section 3.33.7). */
34 :
35 : enum class kind
36 : {
37 : unknown,
38 :
39 : /* Kinds within executable code. */
40 : function,
41 : member,
42 : module_,
43 : namespace_,
44 : type,
45 : return_type,
46 : parameter,
47 : variable,
48 :
49 : /* Kinds within XML or HTML documents. */
50 : element,
51 : attribute,
52 : text,
53 : comment,
54 : processing_instruction,
55 : dtd,
56 : declaration,
57 :
58 : /* Kinds within JSON documents. */
59 : object,
60 : array,
61 : property,
62 : value
63 : };
64 :
65 : /* We want to efficiently support passing around logical locations in the
66 : diagnostics subsystem, such as:
67 : - "within function 'foo'", or
68 : - "within method 'bar'"
69 :
70 : However we want to do this *without* requiring knowledge of trees (or of
71 : libgdiagnostics internals), and without requiring heap allocation of an
72 : interface class when emitting a diagnostic.
73 :
74 : To do this, we split the implementation into logical_locations::key, which is
75 : a wrapper around a (const void *), and logical_locations::manager which
76 : is provided by the client and has vfunc hooks for interpreting
77 : key instances.
78 :
79 : Every logical_locations::key is associated with a logical_locations::manager
80 : and only has meaning in relation to that manager.
81 :
82 : A "nullptr" within a key means "no logical location".
83 :
84 : See tree-logical-location.h for concrete subclasses relating to trees,
85 : where the pointer is a const_tree.
86 :
87 : See diagnostics/selftest-logical-locations.h for a concrete subclass for
88 : selftests. */
89 :
90 : /* Extrinsic state for identifying a specific logical location.
91 : This will be our logical location type.
92 : This only makes sense with respect to a specific manager.
93 : e.g. for a tree-based one it's a wrapper around "tree".
94 :
95 : "nullptr" means "no logical location".
96 :
97 : Note that there is no integration with GCC's garbage collector and thus
98 : keys can't be long-lived. */
99 :
100 : class key
101 : {
102 : public:
103 3109 : key () : m_ptr (nullptr) {}
104 :
105 71693 : static key from_ptr (const void *ptr)
106 : {
107 71693 : return key (ptr);
108 : }
109 :
110 8487 : operator bool () const
111 : {
112 8487 : return m_ptr != nullptr;
113 : }
114 :
115 : template <typename T>
116 : T cast_to () const { return static_cast<T> (m_ptr); }
117 :
118 : bool
119 6264 : operator== (const key &other) const
120 : {
121 6264 : return m_ptr == other.m_ptr;
122 : }
123 :
124 : bool
125 99 : operator!= (const key &other) const
126 : {
127 99 : return m_ptr != other.m_ptr;
128 : }
129 :
130 : bool
131 88 : operator< (const key &other) const
132 : {
133 88 : return m_ptr < other.m_ptr;
134 : }
135 :
136 : private:
137 71618 : explicit key (const void *ptr) : m_ptr (ptr) {}
138 :
139 : const void *m_ptr;
140 : };
141 :
142 : /* Abstract base class for giving meaning to keys.
143 : Typically there will just be one client-provided instance, of a
144 : client-specific subclass. */
145 :
146 1230321 : class manager
147 : {
148 : public:
149 1668 : virtual ~manager () {}
150 :
151 : virtual void dump (FILE *out, int indent) const = 0;
152 0 : void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
153 :
154 : /* vfuncs for interpreting keys. */
155 :
156 : /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
157 : "name" property (SARIF v2.1.0 section 3.33.4). */
158 : virtual label_text get_short_name (key k) const = 0;
159 :
160 : /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
161 : "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
162 : virtual label_text get_name_with_scope (key k) const = 0;
163 :
164 : /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
165 : "decoratedName" property (SARIF v2.1.0 section 3.33.6). */
166 : virtual label_text get_internal_name (key k) const = 0;
167 :
168 : /* Get what kind of SARIF logicalLocation K is (if any). */
169 : virtual enum kind get_kind (key k) const = 0;
170 :
171 : /* Get a string for location K in a form suitable for path output. */
172 : virtual label_text get_name_for_path_output (key k) const = 0;
173 :
174 : /* Get the parent logical_logical of K, if any, or nullptr. */
175 : virtual key get_parent (key k) const = 0;
176 :
177 : bool function_p (key k) const;
178 : };
179 :
180 : } // namespace diagnostics::logical_locations
181 : } // namespace diagnostics
182 :
183 : #endif /* GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H. */
|