/* Parser definitions for GDB.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo.
then look up the macro definitions active at that point. */
extern CORE_ADDR expression_context_pc;
+/* While parsing expressions we need to track the innermost lexical block
+ that we encounter. In some situations we need to track the innermost
+ block just for symbols, and in other situations we want to track the
+ innermost block for symbols and registers. These flags are used by the
+ innermost block tracker to control which blocks we consider for the
+ innermost block. These flags can be combined together as needed. */
+
+enum innermost_block_tracker_type
+{
+ /* Track the innermost block for symbols within an expression. */
+ INNERMOST_BLOCK_FOR_SYMBOLS = (1 << 0),
+
+ /* Track the innermost block for registers within an expression. */
+ INNERMOST_BLOCK_FOR_REGISTERS = (1 << 1)
+};
+DEF_ENUM_FLAGS_TYPE (enum innermost_block_tracker_type,
+ innermost_block_tracker_types);
+
+/* When parsing expressions we track the innermost block that was
+ referenced. */
+
+class innermost_block_tracker
+{
+public:
+ innermost_block_tracker ()
+ : m_types (INNERMOST_BLOCK_FOR_SYMBOLS),
+ m_innermost_block (NULL)
+ { /* Nothing. */ }
+
+ /* Reset the currently stored innermost block. Usually called before
+ parsing a new expression. As the most common case is that we only
+ want to gather the innermost block for symbols in an expression, this
+ becomes the default block tracker type. */
+ void reset (innermost_block_tracker_types t = INNERMOST_BLOCK_FOR_SYMBOLS)
+ {
+ m_types = t;
+ m_innermost_block = NULL;
+ }
+
+ /* Update the stored innermost block if the new block B is more inner
+ than the currently stored block, or if no block is stored yet. The
+ type T tells us whether the block B was for a symbol or for a
+ register. The stored innermost block is only updated if the type T is
+ a type we are interested in, the types we are interested in are held
+ in M_TYPES and set during RESET. */
+ void update (const struct block *b, innermost_block_tracker_types t);
+
+ /* Overload of main UPDATE method which extracts the block from BS. */
+ void update (const struct block_symbol &bs)
+ {
+ update (bs.block, INNERMOST_BLOCK_FOR_SYMBOLS);
+ }
+
+ /* Return the stored innermost block. Can be nullptr if no symbols or
+ registers were found during an expression parse, and so no innermost
+ block was defined. */
+ const struct block *block () const
+ {
+ return m_innermost_block;
+ }
+
+private:
+ /* The type of innermost block being looked for. */
+ innermost_block_tracker_types m_types;
+
+ /* The currently stored innermost block found while parsing an
+ expression. */
+ const struct block *m_innermost_block;
+};
+
/* The innermost context required by the stack and register variables
- we've encountered so far. */
-extern const struct block *innermost_block;
+ we've encountered so far. This should be cleared before parsing an
+ expression, and queried once the parse is complete. */
+extern innermost_block_tracker innermost_block;
/* Number of arguments seen so far in innermost function call. */
extern int arglist_len;