aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostics/logical-locations.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostics/logical-locations.h')
-rw-r--r--gcc/diagnostics/logical-locations.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/gcc/diagnostics/logical-locations.h b/gcc/diagnostics/logical-locations.h
new file mode 100644
index 0000000..b52a9b4
--- /dev/null
+++ b/gcc/diagnostics/logical-locations.h
@@ -0,0 +1,180 @@
+/* Logical location support, without knowledge of "tree".
+ Copyright (C) 2022-2025 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
+#define GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H
+
+#include "label-text.h"
+
+namespace diagnostics {
+namespace logical_locations {
+
+/* An enum for discriminating between different kinds of logical location
+ for a diagnostic.
+
+ Roughly corresponds to logicalLocation's "kind" property in SARIF v2.1.0
+ (section 3.33.7). */
+
+enum class kind
+{
+ unknown,
+
+ /* Kinds within executable code. */
+ function,
+ member,
+ module_,
+ namespace_,
+ type,
+ return_type,
+ parameter,
+ variable,
+
+ /* Kinds within XML or HTML documents. */
+ element,
+ attribute,
+ text,
+ comment,
+ processing_instruction,
+ dtd,
+ declaration,
+
+ /* Kinds within JSON documents. */
+ object,
+ array,
+ property,
+ value
+};
+
+/* We want to efficiently support passing around logical locations in the
+ diagnostics subsystem, such as:
+ - "within function 'foo'", or
+ - "within method 'bar'"
+
+ However we want to do this *without* requiring knowledge of trees (or of
+ libgdiagnostics internals), and without requiring heap allocation of an
+ interface class when emitting a diagnostic.
+
+ To do this, we split the implementation into logical_locations::key, which is
+ a wrapper around a (const void *), and logical_locations::manager which
+ is provided by the client and has vfunc hooks for interpreting
+ key instances.
+
+ Every logical_locations::key is associated with a logical_locations::manager
+ and only has meaning in relation to that manager.
+
+ A "nullptr" within a key means "no logical location".
+
+ See tree-logical-location.h for concrete subclasses relating to trees,
+ where the pointer is a const_tree.
+
+ See diagnostics/selftest-logical-locations.h for a concrete subclass for
+ selftests. */
+
+/* Extrinsic state for identifying a specific logical location.
+ This will be our logical location type.
+ This only makes sense with respect to a specific manager.
+ e.g. for a tree-based one it's a wrapper around "tree".
+
+ "nullptr" means "no logical location".
+
+ Note that there is no integration with GCC's garbage collector and thus
+ keys can't be long-lived. */
+
+class key
+{
+public:
+ key () : m_ptr (nullptr) {}
+
+ static key from_ptr (const void *ptr)
+ {
+ return key (ptr);
+ }
+
+ operator bool () const
+ {
+ return m_ptr != nullptr;
+ }
+
+ template <typename T>
+ T cast_to () const { return static_cast<T> (m_ptr); }
+
+ bool
+ operator== (const key &other) const
+ {
+ return m_ptr == other.m_ptr;
+ }
+
+ bool
+ operator!= (const key &other) const
+ {
+ return m_ptr != other.m_ptr;
+ }
+
+ bool
+ operator< (const key &other) const
+ {
+ return m_ptr < other.m_ptr;
+ }
+
+private:
+ explicit key (const void *ptr) : m_ptr (ptr) {}
+
+ const void *m_ptr;
+};
+
+/* Abstract base class for giving meaning to keys.
+ Typically there will just be one client-provided instance, of a
+ client-specific subclass. */
+
+class manager
+{
+public:
+ virtual ~manager () {}
+
+ /* vfuncs for interpreting keys. */
+
+ /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+ "name" property (SARIF v2.1.0 section 3.33.4). */
+ virtual const char *get_short_name (key k) const = 0;
+
+ /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+ "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5). */
+ virtual const char *get_name_with_scope (key k) const = 0;
+
+ /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
+ "decoratedName" property (SARIF v2.1.0 section 3.33.6). */
+ virtual const char *get_internal_name (key k) const = 0;
+
+ /* Get what kind of SARIF logicalLocation K is (if any). */
+ virtual enum kind get_kind (key k) const = 0;
+
+ /* Get a string for location K in a form suitable for path output. */
+ virtual label_text get_name_for_path_output (key k) const = 0;
+
+ /* Get the parent logical_logical of K, if any, or nullptr. */
+ virtual key get_parent (key k) const = 0;
+
+ bool function_p (key k) const;
+};
+
+} // namespace diagnostics::logical_locations
+} // namespace diagnostics
+
+#endif /* GCC_DIAGNOSTICS_LOGICAL_LOCATIONS_H. */