/* DWARF attributes

   Copyright (C) 1994-2025 Free Software Foundation, Inc.

   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
   Inc.  with support from Florida State University (under contract
   with the Ada Joint Program Office), and Silicon Graphics, Inc.
   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
   support.

   This file is part of GDB.

   This program 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 of the License, or
   (at your option) any later version.

   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef GDB_DWARF2_ATTRIBUTE_H
#define GDB_DWARF2_ATTRIBUTE_H

#include "dwarf2.h"
#include "dwarf2/types.h"

/* Blocks are a bunch of untyped bytes.  */
struct dwarf_block
{
  size_t size;

  /* Valid only if SIZE is not zero.  */
  const gdb_byte *data;
};

/* Attributes have a name and a value.  */
struct attribute
{
  /* Read the given attribute value as an address, taking the
     attribute's form into account.  */
  unrelocated_addr as_address () const;

  /* If the attribute has a string form, return the string value;
     otherwise return NULL.  */
  const char *as_string () const;

  /* Return the block value.  The attribute must have block form.  */
  dwarf_block *as_block () const
  {
    gdb_assert (form_is_block ());
    return u.blk;
  }

  /* Return the signature.  The attribute must have signature
     form.  */
  ULONGEST as_signature () const
  {
    gdb_assert (form == DW_FORM_ref_sig8);
    return u.signature;
  }

  /* Return the signed value.  The attribute must have the appropriate
     form.  */
  LONGEST as_signed () const
  {
    gdb_assert (form_is_strictly_signed ());
    return u.snd;
  }

  /* Return the unsigned value, but only for attributes requiring
     reprocessing.  */
  ULONGEST as_unsigned_reprocess () const
  {
    gdb_assert (form_requires_reprocessing ());
    gdb_assert (requires_reprocessing);
    return u.unsnd;
  }

  /* Return the unsigned value.  Requires that the form be an unsigned
     form, and that reprocessing not be needed.  */
  ULONGEST as_unsigned () const
  {
    gdb_assert (form_is_unsigned ());
    gdb_assert (!requires_reprocessing);
    return u.unsnd;
  }

  /* Return non-zero if ATTR's value is a section offset --- classes
     lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise.
     You may use the as_unsigned method to retrieve such offsets.

     Section 7.5.4, "Attribute Encodings", explains that no attribute
     may have a value that belongs to more than one of these classes; it
     would be ambiguous if we did, because we use the same forms for all
     of them.  */

  bool form_is_section_offset () const;

  /* Return an unsigned constant value.  This only handles constant
     forms (i.e., form_is_constant -- and not the extended list of
     "unsigned" forms) and assumes an unsigned value is desired.  This
     can be used with DWARF-defined enumerations like DW_CC_* or
     DW_INL_*, but also in situations where a nonnegative constant
     integer is specified by DWARF.

     If a signed form and negative value is used, or if a non-constant
     form is used, then complaint is issued and an empty value is
     returned.  */
  std::optional<ULONGEST> unsigned_constant () const;

  /* Return a signed constant value.  This only handles constant forms
     (i.e., form_is_constant -- and not the extended list of
     "unsigned" forms) and assumes a signed value is desired.  This
     function will sign-extend DW_FORM_data* values.

     If non-constant form is used, then complaint is issued and an
     empty value is returned.  */
  std::optional<LONGEST> signed_constant () const;

  /* Return a signed constant value.  However, for narrow forms like
     DW_FORM_data1, sign extension is not done.

     DWARF advises compilers to generally use DW_FORM_[su]data to
     avoid ambiguity.  However, both GCC and LLVM ignore this for
     certain attributes.  Furthermore in DWARF, whether a narrower
     form causes sign-extension depends on the attribute -- for
     attributes that can only assume non-negative values, sign
     extension is not done.

     Unfortunately, both compilers also emit certain attributes in a
     "confused" way, using DW_FORM_sdata for signed values, and
     possibly choosing a narrow form (e.g., DW_FORM_data1) otherwise
     -- assuming that sign-extension will not be done.

     This method should only be called when this "confused" treatment
     is necessary.  */
  std::optional<LONGEST> confused_constant () const;

  /* Return non-zero if ATTR's value falls in the 'constant' class, or
     zero otherwise.  When this function returns true, you can apply
     the constant_value method to it.

     However, note that for some attributes you must check
     attr_form_is_section_offset before using this test.  DW_FORM_data4
     and DW_FORM_data8 are members of both the constant class, and of
     the classes that contain offsets into other debug sections
     (lineptr, loclistptr, macptr or rangelistptr).  The DWARF spec says
     that, if an attribute's can be either a constant or one of the
     section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
     taken as section offsets, not constants.

     DW_FORM_data16 is not considered as constant_value cannot handle
     that.  */

  bool form_is_constant () const;

  /* The address is always stored already as sect_offset; despite for
     the forms besides DW_FORM_ref_addr it is stored as cu_offset in
     the DWARF file.  */

  bool form_is_ref () const
  {
    return (form == DW_FORM_ref_addr
	    || form == DW_FORM_ref1
	    || form == DW_FORM_ref2
	    || form == DW_FORM_ref4
	    || form == DW_FORM_ref8
	    || form == DW_FORM_ref_udata
	    || form == DW_FORM_GNU_ref_alt
	    || form == DW_FORM_ref_sup4
	    || form == DW_FORM_ref_sup8);
  }

  /* Check if the attribute's form is a DW_FORM_block*
     if so return true else false.  */

  bool form_is_block () const;

  /* Check if the attribute's form is a string form.  */
  bool form_is_string () const;

  /* Check if the attribute's form is an unsigned integer form.  */
  bool form_is_unsigned () const;

  /* Check if the attribute's form is a signed integer form.  This
     only returns true for forms that are strictly signed -- that is,
     for a context-dependent form like DW_FORM_data1, this returns
     false.  */
  bool form_is_strictly_signed () const;

  /* Check if the attribute's form is an unsigned constant form.  This
     only returns true for forms that are strictly unsigned -- that
     is, for a context-dependent form like DW_FORM_data1, this returns
     false.  */
  bool form_is_strictly_unsigned () const
  {
    return form == DW_FORM_udata;
  }

  /* Check if the attribute's form is a form that requires
     "reprocessing".  */
  bool form_requires_reprocessing () const;

  /* Check if attribute's form refers to the separate "dwz" file.
     This is only useful for references to the .debug_info section,
     not to the supplementary .debug_str section.  */
  bool form_is_alt () const
  {
    return (form == DW_FORM_GNU_ref_alt
	    || form == DW_FORM_ref_sup4
	    || form == DW_FORM_ref_sup8);
  }

  /* Return DIE offset of this attribute.  Return 0 with complaint if
     the attribute is not of the required kind.  */

  sect_offset get_ref_die_offset () const
  {
    if (form_is_ref ())
      return (sect_offset) u.unsnd;
    get_ref_die_offset_complaint ();
    return {};
  }

  /* Return the constant value held by this attribute.  Return
     DEFAULT_VALUE if the value held by the attribute is not
     constant.  */

  LONGEST constant_value (int default_value) const;

  /* Return true if this attribute holds a canonical string.  In some
     cases, like C++ names, gdb will rewrite the name of a DIE to a
     canonical form.  This makes lookups robust when a name can be
     spelled different ways (e.g., "signed" or "signed int").  This
     flag indicates whether the value has been canonicalized.  */
  bool canonical_string_p () const
  {
    gdb_assert (form_is_string ());
    return string_is_canonical;
  }

  /* Initialize this attribute to hold a non-canonical string
     value.  */
  void set_string_noncanonical (const char *str)
  {
    gdb_assert (form_is_string ());
    u.str = str;
    string_is_canonical = 0;
    requires_reprocessing = 0;
  }

  /* Set the canonical string value for this attribute.  */
  void set_string_canonical (const char *str)
  {
    gdb_assert (form_is_string ());
    u.str = str;
    string_is_canonical = 1;
  }

  /* Set the block value for this attribute.  */
  void set_block (dwarf_block *blk)
  {
    gdb_assert (form_is_block ());
    u.blk = blk;
  }

  /* Set the signature value for this attribute.  */
  void set_signature (ULONGEST signature)
  {
    gdb_assert (form == DW_FORM_ref_sig8);
    u.signature = signature;
  }

  /* Set this attribute to a signed integer.  */
  void set_signed (LONGEST snd)
  {
    gdb_assert (form == DW_FORM_sdata || form == DW_FORM_implicit_const);
    u.snd = snd;
  }

  /* Set this attribute to an unsigned integer.  */
  void set_unsigned (ULONGEST unsnd)
  {
    gdb_assert (form_is_unsigned ());
    u.unsnd = unsnd;
    requires_reprocessing = 0;
  }

  /* Temporarily set this attribute to an unsigned integer.  This is
     used only for those forms that require reprocessing.  */
  void set_unsigned_reprocess (ULONGEST unsnd)
  {
    gdb_assert (form_requires_reprocessing ());
    u.unsnd = unsnd;
    requires_reprocessing = 1;
  }

  /* Set this attribute to an address.  */
  void set_address (unrelocated_addr addr)
  {
    gdb_assert (form == DW_FORM_addr
		|| ((form == DW_FORM_addrx
		     || form == DW_FORM_GNU_addr_index)
		    && requires_reprocessing));
    u.addr = addr;
    requires_reprocessing = 0;
  }

  /* True if this attribute requires reprocessing.  */
  bool requires_reprocessing_p () const
  {
    return requires_reprocessing;
  }

  /* Return the value as one of the recognized enum
     dwarf_defaulted_attribute constants according to DWARF5 spec,
     Table 7.24.  If the value is incorrect, or if this attribute has
     the wrong form, then a complaint is issued and DW_DEFAULTED_no is
     returned.  */
  dwarf_defaulted_attribute defaulted () const;

  /* Return the attribute's value as a dwarf_virtuality_attribute
     constant according to DWARF spec.  An unrecognized value will
     issue a complaint and return DW_VIRTUALITY_none.  */
  dwarf_virtuality_attribute as_virtuality () const;

  /* Return the attribute's value as a boolean.  An unrecognized form
     will issue a complaint and return false.  */
  bool as_boolean () const;

  ENUM_BITFIELD(dwarf_attribute) name : 15;

  /* A boolean that is used for forms that require reprocessing.  A
     form may require data not directly available in the attribute.
     E.g., DW_FORM_strx requires the corresponding
     DW_AT_str_offsets_base.  In this case, the processing for the
     attribute must be done in two passes.  In the first past, this
     flag is set and the value is an unsigned.  In the second pass,
     the unsigned value is turned into the correct value for the form,
     and this flag is cleared.  This flag is unused for other
     forms.  */
  unsigned int requires_reprocessing : 1;

  ENUM_BITFIELD(dwarf_form) form : 15;

  /* Has u.str already been updated by dwarf2_canonicalize_name?  This
     field should be in u.str but it is kept here for better struct
     attribute alignment.  */
  unsigned int string_is_canonical : 1;

  union
    {
      const char *str;
      struct dwarf_block *blk;
      ULONGEST unsnd;
      LONGEST snd;
      unrelocated_addr addr;
      ULONGEST signature;
    }
  u;

private:

  /* Used by get_ref_die_offset to issue a complaint.  */

  void get_ref_die_offset_complaint () const;
};

#endif /* GDB_DWARF2_ATTRIBUTE_H */
